⚠️Flutter的 状态管理⚠️

👏欢迎前往本人的GitHub查看更多内容。点击前往GitHubreact

1 对于状态管理的理解

最近项目开发完成后,没有什么任务安排,就本身对项目进行了查缺补漏。若是说flutter开发中最不可避免的话,确定是状态管理啦。咱们本身的项目当中用的是Provider来进行管理的,本身其实对于状态管理的基础仍是有一点模糊,粗浅的理解就是:避免对页面不停的build,要进行针对性的刷新,(列入:更新一个text也将整个页面build一次浪费性能。)git



1.0 那咱们来言归正传说一说比较正确的理解吧,避免我在这里误人子弟。

1.状态管理的目的就是为了让界面与业务分离。
2.当咱们的应用功能复杂多样的时候,应用程序将会有几十个甚至上百个状态,这时候咱们须要对状态进行合理有效的管理。
复制代码

不少从命令式编程框架(Android或iOS原生开发者)转成声明式编程(Flutter、Vue、React等)刚开始并不适应,由于须要一个新的角度来考虑APP的开发模式。

Flutter做为一个现代的框架,是声明式编程的:

在编写一个应用的过程当中,咱们有大量的状态须要来进行管理,而正是对这些State的改变,来更新界面的刷新:




2 状态管理框架

能够经过以下方式来进行状态管理

1.setState :
最重要的方式 setState,支持规模较小的程序足够了,全部其它方式最终都须要调用 setState。

2.Function callback
Dart Function 足够灵活,还支持模版参数。
typedef FooChanged = void Function(int);
typedef ValueChanged<T> = void Function(T value);
单向变动通知,能够和ObserverList结合支持多个订阅者。
Flutter 内置 ChangeNotifier, ValueNotifier 均可以认为是相似方案。

3.Delegate
能够认为是多个回调函数,其余语言里都有相似模式,名称彷佛来源于 Objective-C。实际例子
abstract class SpiderDelegate {
  /// category is null, crawl book whole site
  /// category not null, crawl book under the category
  void onBook(Book book, {Site site, Category category});

  void onChapter(Book book, Chapter chapter);
}


4.Sigslot
源自 Qt 里的经典编程模式,Dart 能够轻易实现。这种方式在 Flutter 里可能根本不会有太多应用,可是因为 Sigslot 在 C++ 领域具备举足轻重的地位,属于界面数据和逻辑解耦合的王者,boost::signal(2)就是明证,在这里列出纯属凑数(本人也实现了一个)。
typedef ValueCallback<E> = void Function(E value);
abstract class Signable<E> {
  // Signable<bool> someValue;
  /// Register a closure to be called when the object notifies its listeners.
  void connect(ValueCallback<E> listener);

  /// Remove a previously registered closure from the list of closures that the
  /// object notifies.
  void disconnect(ValueCallback<E> listener);

  /// sink value changed
  void emit(E value);
}

使用方法相似
Signal<String> signalString;
signalString.connect((String str) {
  // got the `str` changed here
});

复制代码


2.1 scoped_model

Scoped_model是一个dart第三方库,提供了让您可以轻松地将数据模型从父Widget传递到它的后代的功能。此外,它还会在模型更新时从新渲染使用该模型的全部子项。
它直接来自于Google正在开发的新系统Fuchsia核心Widgets 中对Model类的简单提取,做为独立使用的独立Flutter插件发布。

Scoped model使用了观察者模式,将数据模型放在父代,后代经过找到父代的model进行数据渲染,最后数据改变时将数据传回,父代再通知全部用到了该model的子代去更新状态。
复制代码


2.2 Redux

Redux是一种单向数据流架构,能够轻松开发,维护和测试应用程序。
复制代码

咱们在Redux中,全部的状态都储存在Store里。这个Store会放在App顶层。
View拿到Store储存的状态(State)并把它映射成视图。View还会与用户进行交互,用户点击按钮滑动屏幕等等,这时会由于交互须要数据发生改变。
Redux让咱们不能让View直接操做数据,而是经过发起一个action来告诉Reducer,状态得改变啦。
这时候Reducer接收到了这个action,他就回去遍历action表,而后找到那个匹配的action,根据action生成新的状态并把新的状态放到Store中。
Store丢弃了老的状态对象,储存了新的状态对象后,就通知全部使用到了这个状态的View更新(相似setState)。这样咱们就可以同步不一样view中的状态了。
复制代码


2.3 BLoC

BLoC是一种利用reactive programming方式构建应用的方法,这是一个由流构成的彻底异步的世界。
复制代码

* 用StreamBuilder包裹有状态的部件,streambuilder将会监听一个流
* 这个流来自于BLoC
* 有状态小部件中的数据来自于监听的流。
* 用户交互手势被检测到,产生了事件。例如按了一下按钮。
* 调用bloc的功能来处理这个事件
* 在bloc中处理完毕后将会吧最新的数据add进流的sink中
* StreamBuilder监听到新的数据,产生一个新的snapshot,并从新调用build方法
* Widget被从新构建
复制代码


2.4 RxDart

RxDart是基于ReactiveX标准API的Dart版本实现,由Dart标准库中Stream扩展而成。所以,RxDart与Dart的相关术语稍有区别:

Dart	RxDart
StreamController	Subject
Stream	Observable
Observable等同于Stream,Subject等同于StreamController,前者均由后者继承而来。
不一样于Dart,RxDart提供了三种StreamController的变体来应用到不一样的场景:

PublishSubject
BehaviorSubject
ReplaySubject
复制代码


2.5 Fish-Redux【推荐👍】

Fish Redux 是一个基于 Redux 数据管理的组装式 flutter 应用框架, 它特别适用于构建中大型的复杂应用。它的特色是配置式组装。
一方面咱们将一个大的页面,对视图和数据层层拆解为互相独立的 Component|Adapter,上层负责组装,下层负责实现;
另外一方面将 Component|Adapter 拆分为 View,Reducer,Effect 等相互独立的上下文无关函数。
因此它会很是干净,易维护,易协做。
Fish Redux 的灵感主要来自于 Redux, Elm, Dva 这样的优秀框架。而 Fish Redux 站在巨人的肩膀上,将集中,分治,复用,隔离作的更进一步。
复制代码


2.7 Provide

和Scoped_model同样,Provide也是借助了InheritWidget,将共享状态放到顶层MaterialApp之上。底层部件经过Provier获取该状态,并经过混合ChangeNotifier通知依赖于该状态的组件刷新。
Provide还提供了Provide.stream,让咱们可以以处理流的方式处理数据,不过目前还有一些问题,不推荐使用。
复制代码


2.6 Provider 【推荐👍👍👍】

2019 Google I/O 大会上重磅消息出了支持 flutter_web 以外,另外一个即是弃用以前的状态管理 Provide,转而推荐类似的库 Provider;虽然只有一个字母之差使用方式差异却很大;小菜初步学习一下新的状态管理库 Provider;
 Flutter 针对不一样类型对象提供了多种不一样的 Provider;Provider 也是借助了 InheritWidget,将共享状态放到顶层 MaterialApp 之上;

复制代码



3 实际开发中遇到的坑

3.1 ⚠️Provider中如何抉择 Consumer 仍是 Selector

当咱们须要更新页面的时候,咱们会用notifyListeners();
可是若是咱们用Consumer来包裹一个listview咱们打印会发现已经build过的item都会从新的build一次。
其实这样有一点不合理,由于咱们只须要更新的是其中一个item。
这时候若是咱们用Selector来处理的话就会发现大有不一样。它只会build咱们须要更新的那个item这样的话就更加合理。
可是使用Selector的话,须要注意的是shouldRebuild用什么来决定是否从新build
复制代码

3.2 ⚠️Provider使用Provider.of(context) 获取顶层数据的坑

若是咱们APage使用Provider.of(context) 获取顶层数据,而后BPage对数据进行了更改,其实会影响到APage的而后会从新运行其 build。
其实咱们command点击of进到底层代码发现,除了context之外还有一个参数listen。
若是咱们在APage设置listen:false,这样就不会由于BPage的操做影响到APage了
复制代码

3.3 ⚠️SingleTickerProviderStateMixin与TickerProviderStateMixin的坑

当使用vsync: this的时候,State对象必须with SingleTickerProviderStateMixin或TickerProviderStateMixin

首先咱们要搞清楚SingleTickerProviderStateMixin于TickerProviderStateMixin的区别:
TickerProviderStateMixin适用于多AnimationController的状况
SingleTickerProviderStateMixin适用于单个AnimationController的状况

其实非必须用TickerProviderStateMixin,建议是用SingleTickerProviderStateMixin的。
1.由于若是 APage 使用 with TickerProviderStateMixin,当从APage 跳转到BPage的时候或从BPage返回到APage的时候你打印会发现都调用了build方法。
2.若是不使用 with TickerProviderStateMixin,当从APage 跳转到BPage的时候或从BPage返回到APage的时候都不会调用了build方法。
复制代码





复制代码

参考来源:github

State managementweb

Flutter移动应用:状态管理编程

Flutter | 状态管理指南篇——Providerredux

八种 Flutter 状态管理-深刻评论bash

相关文章
相关标签/搜索