Flutter与MobX的那些事

开始

在之前的一篇文章中,半行代码 介绍到在 Flutter 里面使用 MobX, 今天咱们就来聊聊 Flutter 和 MobX 的那些事。前端

这篇文章的大部份内容能够在 MobX.dart 中看到更原汁原味的介绍。阅读本篇文章阅读约需 30 分钟。react

咱们先来看看 MobX 是什么,根据README的介绍数据库

使用透明的函数响应式编程加强 Dart 程序中的状态管理
复制代码

是前端里大名鼎鼎的 MobX.js 的 Dart 版本。编程

概念

那么,MobX.Dart 有哪些概念,反应了本身函数响应式编程的特性呢?bash

这里关系到 MobX 的 3 个重要概念:微信

  • Observables: Observables 表示响应式的状态。状态很容易理解,就是应用程序里面的状态,或者数据。响应式,就是能够感知到,可观察到数据的变化,也就是咱们常常接触到的 观察者模式
  • Actions: Actions 就是一系列能够引起状态发生变化的动做
  • Reactions:上面提到状态是可观察的,那么这里的 Reactions 就是状态的观察者,状态发生改变的时候,他们能够收到数据变化的通知。

关于 Observables,还有一些更多的概念:网络

Computed Observables

顾名思义,被计算出来的 Observables。在一个应用中,咱们实际上有 2 种状态,这里分别称为 core-statederived-statecore-state 指的就是一个对象本来就存在的状态,例如一我的有本身的firstname和lastname,姓和名是人固有的状态。那么 firstname + lastname,就动态的出来了咱们”姓名“的结果。这个就是咱们的 derived-state。固然这里是一个很基础的例子,现实中咱们的业务多是几个固有属性,经过一个复杂的计算算出了一个最终的结果。这个最终结果实际上也是这个对象的一种状态,它也须要被感知到变化。架构

这里套用 MobX 的一张图来表示他的核心概念:框架

image

show code

咱们来看看 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 结合在一块儿。

  • Widget: UI,状态的可视化表示
  • Store:处理状态
  • Service:逻辑操做,包括复杂逻辑,网络请求,本地数据库存储等等

最佳的代码结构以下:

image

其中:

UI 层应该尽可能使用 StatelessWidgetObserver 结合, 减小 Widget 的 rebuild 次数,提高性能。

Store里面放的 @observable 对象,由于 Dart 在 Flutter 是不能进行运行时反射的,因此复杂对象须要咱们本身进行 observable 的声明。不然不会生效。当须要处理衍生状态的时候,可用 computed 替代。

到这里,其实咱们在使用 MobX 的时候能够组织出职责分层很明确的函数响应式应用架构。可是不一样的页面如何持有 Store 对象,也成了一个问题,固然这个问题在全部的分层架构里都存在。

最简单的是直接写单例的 store, 可是单例的弊端很是明显。咱们须要的是在这几个页面这个对象是同一个,超出这个范围,对象能够销毁,或者使用的是另外一个对象。很直接的咱们就会须要一个对象管理框架,即 依赖注入

针对这点,官方也给出了本身的建议,可使用 Provider 这个框架达到依赖注入的目的。在他的官方文档介绍里,也说本身是一个介于 DI 和 状态管理之间的框架。在这篇文章就不赘述 Provider的使用,感兴趣的朋友能够查看:provider的文档

小结

使用 MobX,咱们能够快速的上手,用一种很简便,容易组织的方式进行 Flutter 的状态管理和代码架构的统一。并且 Store 自然的分开能够写一堆。不会存在 Redux 顶级状态管理难以分而治之的问题。对于异步场景的处理也比 Redux 简单。比较推荐给你们。

请关注个人微信公众号 【半行代码】

相关文章
相关标签/搜索