Says flutter---08状态管理

180 阅读2分钟

InheritedWidget(不咋使用)

  • 原理
    1.定义一个共享数据的类HYShareData且继承自InheritedWidget,该类中做了四件事:
      定义共享的数据;
      定义构造方法,初始化数据及child(下面需要数据的组件要被该类包裹用到child属性);
      获取组件最近的当前InheritedWidget,通过定义类方法HYShareData.of();
      重写父类的抽象方法updateShouldNotify(HYShareData oldWidget),返回false,不执行依赖当前的InheritedWidget的State中的didChangeDependencies。
    2.在需要数据的组件上包裹该类,并且绑定数据属性。
    3.在需要数据的地方通过类方法HYShareData.of(context).数据获得。
    
  • 实现部分代码
    1.定义共享数据的类
      class HYShareData extends InheritedWidget {
    //  1。定义共享的数据
      final int count;
    //  2。定义构造方法,要有参数child,因为下面需要数据的组件要被该类包裹
      HYShareData({this.count,Widget child}):super(child:child);
    //  3。获取组件最近的当前InheritedWidget
      static HYShareData of(BuildContext context){
        return context.dependOnInheritedWidgetOfExactType();
      }
    //  重写父类抽象方法。要不要回调State中的didChangeDependencies;
    //  如果返回true,则执行依赖当前的InheritedWidget的State中的didChangeDependencies
     @override
      bool updateShouldNotify(HYShareData oldWidget) {
        return oldWidget.count != count;
      }
    }
    2.类包裹组件
      body: HYShareData(
            count: _count,
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  HYData01(),
                ],
              ),
            ),
          ),
    3.获得数据
      当前计数:${HYShareData.of(context).count}
    

Provider(官方推荐)

provider.of()+consumer()

  • 特点
    优点:代码简单整洁;
    缺点:当我们点击了floatingActionButton时,HYHomePage的build方法会被重新调用,这意味着整个HYHomePage的Widget都需要重新build,浪费性能。
    
  • 实现原理
    1.创建自己的ChangeNotifier继承自ChangeNotifier来保存数据;
    2.把ChangeNotifierProvider插入到widget树即应用程序的顶层;
    3.在操作数据的地方引入Consumer被其包裹修改数据状态;
    4.在需要数据的地方使用Provider.of<自定义类>(context).数据名来获取;
    
  • 部分代码实现
    1.创建自己的ChangeNotifierclass HYShareData extends ChangeNotifier {
        int _count = 10;
        int get count => _count;
        set count(int value) {
          _count = value;
          notifyListeners(); //set一旦检测到数据有变化,该方法通知所有的consumer进行数据更新
        }
      }
    2.把ChangeNotifierProvider插入顶层树
      main(){
        runApp(
          ChangeNotifierProvider(
            create: (context) => HYShareData(),
            child: MyApp(),
          )
        );
      }
    3.包裹consumer
      body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                HYData1(),
              ],
            ),
          ),
    4.获取数据
      int count = Provider.of<HYShareData>(context).count;
      return Container(
          child: Text('当前计数:$count',style: TextStyle(fontSize: 20)),
      );
    

consumer()+consumer()

  • 特点
    优点:Consumer在刷新整个Widget树时,会尽可能少的rebuild Widget;
    缺点:代码比provider.of()多,会刷新操作数据的build方法。
    
  • 实现
    其他步骤与provider.of()+consumer一致,只是在需要使用数据的地方不再通过provider获取,而是通过包裹consumer获取:
    return Consumer<HYShareData>(
        builder: (context,value,child){
          return Text('当前计数:${value.count}',style: TextStyle(fontSize: 20));
        },
      );
    

selector()+consumer()

  • 特点
    不会刷新操作数据(在这里指的是改变数据的按钮floatingActionButton)的build方法。
    
  • 实现
    在操作数据的地方即floatingActionButton传入Selector():
    floatingActionButton: Selector<HYShareData1,HYShareData2>(
    //  方法selector的作用是传入一个 HYShareData1 返回一个 HYShareData2,把HYShareData1转换成HYShareData2类型,可以做类型转换。
    //  builder传入一个函数其对应的泛型是HYShareData2。
            selector: (context,provider) => provider,
            shouldRebuild: (pre,next) => false,
            builder: (context,ShareData2,child){
              return FloatingActionButton(
                child: child,
                onPressed: (){
                  ShareData2.count++; //ShareData2的类型是HYShareData2类
                },
              );
            },
            child: Icon(Icons.add),
          )
    

多个provider管理多个数据

runApp(MultiProvider(
providers: [
  ChangeNotifierProvider(create: (ctx) => CounterProvider()),
  ChangeNotifierProvider(create: (ctx) => UserProvider()),
],
child: MyApp(),
));