Flutter-状态管理

119 阅读2分钟

Flutter-状态管理

InheritedWidget管理方式

MJYCounterWidget(
        counter: _counter,
        child: Column(
          children: [MJYShowData01(), MJYShowData02()],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          setState(() {
            _counter++;
          });
        },
      ),
class MJYCounterWidget extends InheritedWidget {
  // 1.共享的数据
  int counter;
​
  // 2.定义构造方法
  MJYCounterWidget({required Widget child, required this.counter})
      : super(child: child);
​
// 3.获取组建最近的当前的InheritedWidget
  static MJYCounterWidget? of(BuildContext ctx) {
    //沿着element数找到最近的MJYCounterElement,从element中取出widget对应的对象
    //
    return ctx.dependOnInheritedWidgetOfExactType();
  }
​
  @override
  // 4.决定要不要回调State中的didChangeDependencies方法
//  如果返回为TRUE,执行依赖当前的InheritedWidget中的State中的didChangeDependencies
  bool updateShouldNotify(covariant InheritedWidget oldWidget) {
    // return true;
    return oldWidget != counter;
  }
}
​
class MJYShowData01 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    int? counter = MJYCounterWidget.of(context)?.counter;
    return Card(
      color: Colors.red,
      child: Text("当前计数:$counter"),
    );
  }
}
​
class MJYShowData02 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    int? counter = MJYCounterWidget.of(context)?.counter;
    return Container(
      color: Colors.blue,
      child: Text("当前计数:$counter"),
    );
  }
}
​

image-20221024214001554

ProVider 官方推荐的全局状态管理工具

  1. 创建自己需要共享的数据
  2. 在我们应用程序的顶层使用ChangeNotifierProvider
  3. 在其他位置使用共享的数据
  4. 两种方式Consumer,使用Consumer会更多,当数据发生改变时因为不会重新构建build全部组件,只会重新构建Consumer的build
  5. 和Provider.of,会重新build整个的widget
  6. Selector:selector,1、对原有的数据进行转化,2、shouldRebuild,要不要重新构建数据模型
需要共享的数据
//with 相当于混入
class MJYCounterStore with ChangeNotifier {
  //  快速生成getter/setter/toString/Construct/快捷键Command+n
 int _counter = 100;
​
 int get counter => _counter;
 void increment() {
   _counter++;
   notifyListeners();
 }
 @override
 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
   properties.add(IntProperty('count', counter));
 }
  set counter(int value) {
    _counter = value;
    // 通知所有的监听者
    notifyListeners();
  }
}
应用程度顶层使用
main() {
  runApp(
      MultiProvider(
        providers: [
          ChangeNotifierProvider(create: (_)=>MJYCounterStore())
        ],
        child: const MYApp(),
      )
  );
}

读取值

最简单的读取值的方式就是使用 BuildContext 上的扩展属性(由 provider 注入)。

  1. context.watch<T>(),widget 能够监听到 T 类型的 provider 发生的改变。
  2. context.read<T>(),直接返回 T,不会监听改变。
  3. context.select<T,R>(R cb(T value)),允许 widget 只监听 T 上的一部分内容的改变。
Scaffold(
  appBar: AppBar(
    title: Text("Provider"),
  ),
  body: Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        MJYShowData01(),
        MJYShowData02(),
        MJYShowData03()
      ],
    ),
  ),
  ///方式3
  floatingActionButton: Selector<MJYCounterStore,MJYCounterStore>(
    selector: (ctx,vm)=>vm,
    shouldRebuild: (prev,next)=>false,
    builder: (ctx,vm,child){
      return FloatingActionButton(
          onPressed: (){
            vm.counter += 1;
          },
          child: child,
          );
    },
    child: Icon(Icons.add),
  ),
  ///方式2
  // floatingActionButton: FloatingActionButton(
  //   key: const Key('increment_floatingActionButton'),
  //
  //   /// Calls `context.read` instead of `context.watch` so that it does not rebuild
  //   /// when [Counter] changes.
  //   onPressed: () => context.read<MJYCounterStore>().increment(),
  //   tooltip: 'Increment',
  //   child: const Icon(Icons.add),
  // ),
)
  1. Consumer方式,可以部分更新
  2. context.watch<T>(),widget 能够监听到 T 类型的 provider 发生的改变
  3. Provider.of<T>(context) 这一静态方法,它的表现类似 watch, 而在你为传入 listen: false 参数时(例如 Provider.of<T>(context,listen: false)), 它的表现与 read 类似
class MJYShowData01 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // int counter = Provider.of<MJYCounterStore>(context).counter;
    return Card(
        color: Colors.red,
        child: Consumer<MJYCounterStore>(
          builder: (ctx, vm, child) {
            return Text(
              "当前计数:${vm.counter}",
              style: Theme.of(context).textTheme.headline4);
          },
        )
    );
  }
}
​
class MJYShowData02 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // int counter = Provider.of<MJYCounterStore>(context).counter;
    return Container(
      color: Colors.blue,
      child: Text(
          '当前计数:${context.watch<MJYCounterStore>().counter}',
          key: const Key('counterState'),
          style: Theme.of(context).textTheme.headline4),
    );
  }
}
class MJYShowData03 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    int counter = Provider.of<MJYCounterStore>(context).counter;
    return Container(
      margin: EdgeInsets.only(top: 5),
      color: Colors.green,
      child: Text(
          '当前计数:$counter',
          key: const Key('counterState'),
          style: Theme.of(context).textTheme.headline4),
    );
  }
}

效果

image-20221025103149187