在之前的一篇文章中,半行代码
介绍到在 Flutter 里面使用 MobX
, 今天咱们就来聊聊 Flutter 和 MobX 的那些事。前端
这篇文章的大部份内容能够在 MobX.dart 中看到更原汁原味的介绍。阅读本篇文章阅读约需 30 分钟。react
咱们先来看看 MobX 是什么,根据README的介绍数据库
使用透明的函数响应式编程加强 Dart 程序中的状态管理
复制代码
是前端里大名鼎鼎的 MobX.js
的 Dart 版本。编程
那么,MobX.Dart 有哪些概念,反应了本身函数响应式编程的特性呢?bash
这里关系到 MobX
的 3 个重要概念:微信
观察者模式
关于 Observables,还有一些更多的概念:网络
顾名思义,被计算出来的 Observables。在一个应用中,咱们实际上有 2 种状态,这里分别称为 core-state
和 derived-state
,core-state
指的就是一个对象本来就存在的状态,例如一我的有本身的firstname和lastname,姓和名是人固有的状态。那么 firstname + lastname,就动态的出来了咱们”姓名“的结果。这个就是咱们的 derived-state
。固然这里是一个很基础的例子,现实中咱们的业务多是几个固有属性,经过一个复杂的计算算出了一个最终的结果。这个最终结果实际上也是这个对象的一种状态,它也须要被感知到变化。架构
这里套用 MobX
的一张图来表示他的核心概念:框架
咱们来看看 Mobx
的具体用法,套用 Flutter 默认的 计数器点击 +1 的例子。less
一个简单的计数器能够表示成一个可观察的数字状态,计数器表示为 Counter 对象:
part 'counter.g.dart';
class Counter = CounterBase with _$Counter; abstract class CounterBase with Store {
@observable
int value = 0;
@action
void increment() {
value++;
}
}
复制代码
这里,Mobx
须要借助 builder_runner
这个库生成对应的 _$Counter
类的代码。具体能够自行 Google。
那么示例中计数器的值怎么反应到 UI 呢?这里就要借助咱们 Flutter-MobX
里的 Widget 啦
final counter = Counter(); // Instantiate the store
Observer(
builder: (_) => Text('${counter.value}',
style: Theme.of(context).textTheme.display1,
),
),
复制代码
这里咱们使用了一个叫作 Observer
的 Widget, builder方法里面把 counter 的 observable 对象的值做为属性传给 Text。
这里在调用 @action
的函数以后,counter 里面的值变化后会自动体如今 UI 上。
这里咱们能够看到,使用了 MobX
,咱们能够尽量的使用 StatelessWidget
,避免了 setState
的混乱。也提高了效率。
那么如何使用 Reaction 完成对他的监听呢,Reaction相关的函数有好几个,这里列举几个比较典型的:
ReactionDisposer autorun(Function(Reaction) fn)
当即执行 fn
import 'package:mobx/mobx.dart';
String greeting = Observable('Hello World');
final dispose = autorun((_){
print(greeting.value);
});
greeting.value = 'Hello MobX';
dispose();
复制代码
这里会输出
Hello World
Hello MobX
复制代码
ReactionDisposer reaction<T>(T Function(Reaction) predicate, void Function(T) effect)
监听 predicate
里面监听 observable,当 predicate
返回了新的对象的时候,调用 effect
函数。
import 'package:mobx/mobx.dart';
String greeting = Observable('Hello World');
final dispose = reaction((_) => greeting.value, (msg) => print(msg));
greeting.value = 'Hello MobX'; // Cause a change
dispose();
复制代码
输出:
Hello MobX
复制代码
ReactionDisposer when(bool Function(Reaction) predicate, void Function() effect)
待条件的响应。在reaction
的基础上加上 predicate
函数返回 true
使用了 MobX
,那么咱们的代码该如何组织呢?通常来讲,咱们的 Store
会按照职责,分到每一个业务相关的 Store
去。
那么,一个业务模块,如何组织它和 UI、逻辑呢?官方给出了建议的方式。将 Widegt - Store - Service 结合在一块儿。
最佳的代码结构以下:
其中:
UI 层应该尽可能使用 StatelessWidget
和 Observer
结合, 减小 Widget 的 rebuild 次数,提高性能。
Store里面放的 @observable
对象,由于 Dart 在 Flutter 是不能进行运行时反射的,因此复杂对象须要咱们本身进行 observable 的声明。不然不会生效。当须要处理衍生状态的时候,可用 computed
替代。
到这里,其实咱们在使用 MobX
的时候能够组织出职责分层很明确的函数响应式应用架构。可是不一样的页面如何持有 Store
对象,也成了一个问题,固然这个问题在全部的分层架构里都存在。
最简单的是直接写单例的 store, 可是单例的弊端很是明显。咱们须要的是在这几个页面这个对象是同一个,超出这个范围,对象能够销毁,或者使用的是另外一个对象。很直接的咱们就会须要一个对象管理框架,即 依赖注入
针对这点,官方也给出了本身的建议,可使用 Provider
这个框架达到依赖注入的目的。在他的官方文档介绍里,也说本身是一个介于 DI 和 状态管理之间的框架。在这篇文章就不赘述 Provider
的使用,感兴趣的朋友能够查看:provider的文档
使用 MobX
,咱们能够快速的上手,用一种很简便,容易组织的方式进行 Flutter 的状态管理和代码架构的统一。并且 Store 自然的分开能够写一堆。不会存在 Redux
顶级状态管理难以分而治之的问题。对于异步场景的处理也比 Redux 简单。比较推荐给你们。
请关注个人微信公众号 【半行代码】