Flutter 状态管理

Flutter 状态管理

InheritedWidget跨组件的数据传递

InheritedWidget和React中的context功能类似,可以实现跨组件数据的传递。

定义一个共享数据的InheritedWidget,需要继承自InheritedWidget

1、InheritedWidget创建

2、方法调用

   

这里通过HYCounterWidget.of(context)去获取最近节点的HYCounterWidget,然后获取里面的counter。

int counter = HYCounterWidget.of(context).counter;

注意:InheritedWidget仅仅用来共享数据,不做数据同步。

在页面间做数据的状态同步或更新,我们常用的是官方推荐的第三方库:provider

provider实现全局数据的同步

provider对于同步数据有两种方式:

  1. Provider.of
  2. consumer

区别:

通过Provider.of获取变量之后,在变量发生更新时,整个widget会重新进行build。Consumer在刷新整个Widget树时,会尽可能少的rebuild Widget

Provider.of使用基本步骤:

在使用Provider的时候,我们主要关心三个概念:

1、ChangeNotifier:真正数据(状态)存放的地方

2、ChangeNotifierProvider:Widget树中提供数据(状态)的地方,会在其中创建对应 ChangeNotifier

3、Consumer:Widget树中需要使用数据(状态)的地方

第一步:创建自己的ChangeNotifier

 

  1. 这里我们可以使用继承自ChangeNotifier,也可以使用混入,这取决于概率是否需要继承自其它的类
  2. 我们使用一个私有的_counter,并且提供了getter和setter
  3. 在setter中我们监听到_counter的改变,就调用notifyListeners方法,通知所有的Consumer进行更新

第二步:在Widget Tree中插入ChangeNotifierProvider

 

我们需要在Widget Tree中插入ChangeNotifierProvider,以便Consumer可以获取到数据:

将ChangeNotifierProvider放到了顶层,这样方便在整个应用的任何地方可以使用CounterProvider

(注意:ChangeNotifierProvider中的HYCounterViewModel是懒加载,只有第一个consumer用到时才会过来加载。)

第三步:在首页中使用Consumer引入和修改状态

引入位置一:在floatingActionButton中使用Consumer,当点击按钮时,修改CounterNotifier中的counter数据;

引入位置二:在body中使用Consumer,Consumer需要传入一个builder回调函数,当数据发生变化时,就会通知依赖数据的Consumer重新调用builder方法来构建;

 

 

Consumer的builder方法解析:

 

参数一:context,每个build方法都会有上下文,目的是知道当前树的位置

参数二:ChangeNotifier对应的实例,也是我们在builder函数中主要使用的对象

参数三:child,目的是进行优化,如果builder下面有一颗庞大的子树,当模型发生改变的时候,我们并不希望重新build这颗子树,那么就可以将这颗子树放到Consumer的child中,在这里直接引入即可(注意我案例中的Icon所放的位置)

Selector优化consumer多余渲染问题

  1. 比如当点击了floatingActionButton时,我们在代码的两处分别打印它们的builder是否会重新调用;
  2. 我们会发现只要点击了floatingActionButton,两个位置都会被重新builder;
  3. 但是floatingActionButton的位置有重新build的必要吗?没有,因为它是否在操作数据,并没有展示;
  4. 如何可以做到让它不要重新build了?使用Selector来代替Consumer

Selector和Consumer对比,不同之处主要是三个关键点:

 

  1. 关键点1:泛型参数是两个
    1. 泛型参数一:我们这次要使用的Provider(原始数据)
    2. 泛型参数二:转换之后的数据类型,比如我这里转换之后依然是使用CounterProvider,那么他们两个就是一样的类型转换之后的数据
  2. 关键点2:selector回调函数
    1. 转换的回调函数,你希望如何进行转换
    2. S Function(BuildContext, A) selector
    3. 我这里没有进行转换,所以直接将A实例返回即可
  3. 关键点3:是否希望重新rebuild
    1. 这里也是一个回调函数,我们可以拿到转换前后的两个实例;
    2. bool Function(T previous, T next);
    3. 因为这里我不希望它重新rebuild,无论数据如何变化,所以这里我直接return false;

MultiProvider解决接收多个状态数据

同一widget需要同时接收多个状态数据,需要采用multiprovider进行处理;

1、将多个provider放到一个List列表中,

 2、通过multiprovider进行包裹

 3、在触发值改变的selector中设置多个值

 4、在值变化的consumer中接收多个值并进行数据处理

ChangeNotifierProxyProvider 同步更新数据

当一个对象的更新会影响到另外一个数据更新的时候,采用ChangeNotifierProxyProvider 进行数据关联更新。

 这里HYFilterViewModel(过滤条件)的更新会对HYMealViewModel(内容)进行更新。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值