flutter状态管理 provider使用

provider是flutter官方推荐的状态管理插件,是基于InheritedWidget实现的。
下面我们来讲一个provider的使用方法。
1.在pubspec.yaml文件中添加 provider: ^6.1.2 开发文档:https://pub-web.flutter-io.cn/packages/provider 可以查看使用方法和最新版本号。
添加完成后,进行保存,VSCode会自动 flutter pub get 安装依赖,如果没有自动安装则手动执行flutter pub get

2..创建一个继承自ChangeNotifier的类 input_provider.dart
ChangeNotifier 是 Flutter SDK 中的一个简单的类。它用于向监听器发送通知。换言之,如果被定义为 ChangeNotifier,你可以订阅它的状态变化。(这和大家所熟悉的观察者模式相类似)。

import 'package:flutter/material.dart';

///监听内容变化
class InputProvider extends ChangeNotifier {
  ///等待改变的内容 可以是普通类型 也可以是 数组、字典、自定义model
  String _inputText = '';
  String get inputText => _inputText;
  set inputText(String value) {
    _inputText = value;
    notifyListeners();
  }
}

3.用MultiProvider包裹MyApp,让MyApp下的子孙节点具备监听状态改变的能力 main.dart代码如下

import 'package:flutter/material.dart';
import 'one_page.dart';
import 'two_page.dart';
import 'package:provider/provider.dart';
import 'input_provider.dart';

void main() {
  runApp(
    // 使用MultiProvider包裹MyApp,使得MyApp下的子孙节点具备Provider的能力
    MultiProvider(
      providers: [
        ChangeNotifierProvider<InputProvider>(
            create: (context) => InputProvider()),
      ],
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        // 不显示debug
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        routes: {
          '/one': (context) => const OnePage(),
          '/two': (context) => const TwoPage(),
        },
        home: const OnePage());
  }
}

4.新建 one_page.dart:实现接收状态改变通知然后更新UI的方法 、 two_page.dart :实现改变状态和更新UI的方法

one_page.dart代码如下:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'input_provider.dart';
import 'two_page.dart';

class OnePage extends StatefulWidget {
  const OnePage({super.key});
  @override
  State<OnePage> createState() => _OnePageState();
}

class _OnePageState extends State<OnePage> {
  late String _text;
  @override
  void initState() {
    _text = 'This is the first page';
    //当文本发生变化时,监听变化内容,并更新文本
    Provider.of<InputProvider>(context, listen: false).addListener(() {
      String text =
          Provider.of<InputProvider>(context, listen: false).inputText;
      setState(() {
        //刷新页面
        _text = text;
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: const Text('One Page')),
        body: Center(
          child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Text(_text),
                ElevatedButton(
                  onPressed: () {
                    //跳转到第二个页面
                    // Navigator.pushNamed(context, '/two');
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => const TwoPage(),
                      ),
                    );
                  },
                  child: const Text('跳转第二个页面'),
                ),
              ]),
        ));
  }
}

two_page.dart代码如下:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'input_provider.dart';

class TwoPage extends StatefulWidget {
  const TwoPage({super.key});
  @override
  State<TwoPage> createState() => _TwoPageState();
}

class _TwoPageState extends State<TwoPage> {
  final TextEditingController _controller = TextEditingController();
  late String _text;
  @override
  void initState() {
    _text = 'This is the second page';
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Two Page')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            //使用Consumer获取InputProvider中的inputText
            Consumer(builder: (context, InputProvider provider, child) {
              return Text(
                  provider.inputText.isEmpty ? _text : provider.inputText);
            }),
            //使用Consumer获取InputProvider中的inputText
            Consumer(
                builder: (context, InputProvider provider, child) => Text(
                    provider.inputText.isEmpty ? _text : provider.inputText)),
            Container(
              padding: const EdgeInsets.only(left: 15, right: 15),
              child: TextField(
                controller: _controller,
                decoration: const InputDecoration(
                  border: OutlineInputBorder(),
                  labelText: '输入内容',
                ),
              ),
            ),
            ElevatedButton(
              onPressed: () {
                _changeText();
              },
              child: const Text('提交改变'),
            ),
          ],
        ),
      ),
    );
  }

  //给inputText赋值,触发监听事件
  _changeText() {
    Provider.of<InputProvider>(context, listen: false).inputText =
        _controller.text;
  }
}

当从TwoPage返回OnePage,再进入到TwoPage,我们会发现 TwoPage显示的还是我们修改过的内容,这是因为 inputText 已经改变,当再次进入的时候获取到的 provider.inputText是有值的,会展示inputText的值而不是默认的 _text = 'This is the second page';




posted @ 2024-07-04 18:43  hczhhm  阅读(52)  评论(0编辑  收藏  举报