Flutter 局部刷新/状态管理 全面总结

21 篇文章 0 订阅
20 篇文章 2 订阅

Flutter 局部刷新/ 状态管理

在Flutter中,如果我们想要更新页面中的某个widget的状态的话,一般会使用setState方法重走build方法来刷新。

//Flutter是描述性的(declarative), UI反映状态.

UI = f(state)

当页面布局复杂的时候,这样肯定是不行的。 这边梳理了下几种常见的方式,做个记录,方便将来选型

总体分为两类:

第一类,Dart 和 Flutter 内置支持

1. setState.

Flutter里面最重要的方式 setState,规模较小的程序足够了,所有其它方式最终都需要调用 setState。

setState((){ 
  _value = "new data"; 
}); 

2. Function callback, 主要的实现有: ChangeNotifier, ValueNotifier

ValueNotifier 里面包含一个 T value 值,当值改变的时候,会通知它的监听来刷新UI

//初始化
  ValueNotifier<int> indexNotifier = ValueNotifier(0);
//数据变更:
indexNotifier.value = value;
//触发UI刷新
 ValueListenableBuilder(
            valueListenable: indexNotifier,
            builder: (BuildContext context, int value, Widget child) {
              return CircleCheckBox(
                size: 40,
                activeColor: Color(periwinkle),
                value: _isSelect(value),
                onChanged: _onSelect,
              );
            },
          )

//销毁
    indexNotifier.dispose();

ValueNofiter 其实跟Android DataBinding 里面的 ObserverField 类似,都是使用一个观察者模式来实现数据驱动UI修改。

使用过程发现,这个类有个bug 当Value 是List是使用,修改数据不会发出通知,需要手动调用 notifyLisener().
搜索了下,Flutter 项目下已经有这个issue了(https://github.com/flutter/flutter/issues/29958) 。 原因是因为,里面判断数据有变更的方法没有对List进行处理。

3. Global Key通信

GlobalKey能够跨Widget访问状态,相比于Flutter的 函数声明式编程 类似 android等其他平台的命令式调用

//初始化:

GlobalKey<SwitcherWidgetState> key = GlobalKey();

//使用:
          key.currentState.changeState();

4. StreamBuilder

StreamBuilder也是官方内置的一种刷新UI方式。数据封装成 通知UI变更

 //步骤1:初始化一个StreamController<可以是 int string...  一般是model> 
  final StreamController<String> _streamController = StreamController<String>();

 //发送
 _streamController.sink.add(_str);
 
 //UI 变更
         child: StreamBuilder<String>(  // 监听Stream,每次值改变的时候,更新Text中的内容
          stream: _streamController.stream,
          initialData: _str,
          builder: (BuildContext context, AsyncSnapshot<int> snapshot){
            return Text('点击的时候这个值会改变: ${snapshot.data}');
          }
        ),

 // 销毁
    _streamController.close();

5. FutureBuilder

通常用于是 异步编程,Future返回值是情况,它的构造方法:

const FutureBuilder({
    Key key,
    this.future,          //获取数据的方法
    this.initialData,   //初始的默认数据
    @required this.builder
  }) : assert(builder != null),
       super(key: key);

第二类,包-外部实现, 待完善

1. provider

provider 是 Google I/O 2019也推荐的状态管理库,网上内容也很多,源代码其实不多,很容易看懂。出自 Flutter dev team,绝对的官方了,总共代码 675行

Hilight里面也是用这个进行状态管理

实现:

  • model类继承ChangeNotifer,
class CounterModel extends ChangeNotifier {
  int value = 0;

  void increment() {
    value++;
    notifyListeners();
  }

  void decrement() {
    value--;
    notifyListeners();
  }
}
  • 数据提供者: ChangeNotifierProvider
void main() => runApp(ChangeNotifierProvider(
      create: (context) => CounterModel(),
      child: MyApp(),
    ));
  • 数据消费者/操纵者, 有两种方式: Consumer包裹, 用Provider.of.
  Consumer<CounterModel>(
    builder: (context, counter, child) => Text(
      '${counter.value}',
    ),
  ),

或者:

 FloatingActionButton(
    onPressed: () =>
        Provider.of<CounterModel>(context, listen: false).increment(),
  ),

Provider性能相关的实现细节

  • Consumer包裹的范围要尽量小.
  • Consumer中builder方法的第三个参数child 可以用于缓存一些并不需要重建的widget:
return Consumer<CartModel>(
  builder: (context, cart, child) => Stack(
        children: [
          // Use SomeExpensiveWidget here, without rebuilding every time.
          child,
          Text("Total price: ${cart.totalPrice}"),
        ],
      ),
  // Build the expensive widget here.
  child: SomeExpensiveWidget(),
);

2. scoped_model

源自 Fuchsia 代码,包括注释也只有 287 行代码。 Scoped Model是基于InheritedWidget的. 思想仍然是把状态提到上层去, 并且封装了状态改变的通知部分。Provider 就是就是这个基础上
再新增 Providers,Provider 支持 Stream

3. InheritedWidget

4. Rxdux

5. Bloc

6. MobX

7.GetX

2021 0708 重新回顾了下,发现这个库挺好用的。定点刷新比较简单。可以大力使用:
flutter 一文带你了解GetX

原理

InheritedWidget

InheritedWidget的主要作用是在Widget树中有效地传递信息.

Flutter中常用的Theme, Style, MediaQuery等就是inherited widget, 所以在程序里的各种地方都可以访问到它们.

InheritedWidget也会用在其他状态管理模式中, 作为传递数据的方法.

当用InheritedWidget做状态管理时, 基本思想就是把状态提上去.当子widgets之间需要共享状态, 那么就把状态保存在它们共有的parent中

InheritedWidget解决了访问状态和根据状态更新的问题, 但是改变state却不太行.

参考:

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值