接上一篇Flutter状态管理之路(三) 
flutter_mobx 版本:
dependencies:
dev_dependencies:
文档:https://mobx.pub/ 
概念 
对象 
说明 
 
 
Observables 
代表响应式状态,可以是普通dart对象, 
 
Computed 
计算属性,根据多个Observables来源计算出 
 
Actions 
响应改变Observables的地方 
 
Reactions 
对Action、Observable、Computed三元素响应的地方, 
 
Observer 
上述Reaction的一个具体实现,用于Flutter中包裹需要响应 
 
 
概念图(来自mobx.pub):
                
                图来自mobx.pub
             
使用例子 来自官网 计数器Demo
定义Store,新建counter.dart 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // Include generated file part 'counter.g.dart';   /// 利用注解解析生成代码 // This is the class used by rest of your codebase class Counter = _Counter with _$Counter; // The store-class abstract class _Counter with Store {   @observable   int value = 0;   @action   void increment() {     value++;   } } 
main.dart 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 final counter = Counter(); // 1. 初始化Store void main() => runApp(MyApp()); class MyApp extends StatelessWidget {   // This widget is the root of your application.   @override   Widget build(BuildContext context) {     return MaterialApp(       title: 'MobX',       theme: ThemeData(         primarySwatch: Colors.blue,       ),       home: const MyHomePage(),     );   } } class MyHomePage extends StatelessWidget {   const MyHomePage();   @override   Widget build(BuildContext context) {     return Scaffold(       appBar: AppBar(         title: Text('MobX Counter'),       ),       body: Center(         child: Column(           mainAxisAlignment: MainAxisAlignment.center,           children: <Widget>[             Text(               'You have pushed the button this many times:',             ),             // Wrapping in the Observer will automatically re-render on changes to counter.value             Observer(   /// 2. 用Observer包裹 使用counter  会自动建立订阅关系               builder: (_) => Text(                 '${counter.value}',                 style: Theme.of(context).textTheme.display1,               ),             ),           ],         ),       ),       floatingActionButton: FloatingActionButton(         onPressed: counter.increment,   /// 3. 调用Observer的setter方法 通知更新         tooltip: 'Increment',         child: Icon(Icons.add),       ),     );   } } 
图示 
                
                flutter_mobx主流程图1.png
             
关键对象 以上述计数器例子来分析下源码中关键对象
_$Counter 该对象由代码生成器生成,主要实现扩展自定义的dart object的Observable的能力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 mixin _$Counter on _Counter, Store {    /// Store只是起标识作用的mixin   /// _Counter是我们自定义的状态对象      final _$valueAtom = Atom(name: '_Counter.value'); /// 根据@observable标识的变量,生成的对应的Atom对象,用于与Reactions实现观察者模式   @override   int get value {   /// 属性value的getter  根据@observable生成     _$valueAtom.context.enforceReadPolicy(_$valueAtom); /// 用于限制此方法是否能在非Actions和Reactions里调用,默认允许,否则抛出assert异常     _$valueAtom.reportObserved();	/// 注册观察者(Reaction)     return super.value;		/// 返回值   }   @override   set value(int value) {     _$valueAtom.context.conditionallyRunInAction(() {     	/// conditionallyRunInAction 用于判断写入的安全策略和是否包含action的追踪       super.value = value;  /// 赋值的地方       _$valueAtom.reportChanged();  /// 通知注册在valueAtom里的Observer刷新数据     }, _$valueAtom, name: '${_$valueAtom.name}_set');   }   final _$_CounterActionController = ActionController(name: '_Counter');	/// 根据@action生成,用于记录action调用情况   @override   void increment() {     final _$actionInfo = _$_CounterActionController.startAction(); /// 记录开始     try {       return super.increment();		/// 真正执行定义的increment方法     } finally {       _$_CounterActionController.endAction(_$actionInfo); /// 记录完成     }   } } 
上述代码片段里的_$valueAtom.context是每个Atom里默认取的全局的MainContext,看Atom构造:
1 2 3 4 5 6 7 8 9 10 class Atom {   factory Atom(           {String name,           Function() onObserved,           Function() onUnobserved,           ReactiveContext context}) =>       Atom._(context ?? mainContext,   /// 注意此处,参数不传会使用mainContext           name: name, onObserved: onObserved, onUnobserved: onUnobserved); 		... } 
看下几个重点方法:
_$valueAtom.context.conditionallyRunInAction 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 void conditionallyRunInAction(void Function() fn, Atom atom,       {String name, ActionController actionController}) {     if (isWithinBatch) {     /// 当在action、reaction里执行时,直接进入此处       enforceWritePolicy(atom);  /// 检查写入权限,如是否可在非action外进行写入等       fn();			/// 执行真正赋值的地方     } else {     /// 非 action or transaction 里执行走这       final controller = actionController ??           ActionController(               context: this, name: name ?? nameFor('conditionallyRunInAction'));       final runInfo = controller.startAction();  /// 记录action开始       try {         enforceWritePolicy(atom);         fn();       } finally {         controller.endAction(runInfo);   ///  记录action结束       }     }   } 
_$valueAtom.reportObserved() 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 	/// Atom void reportObserved() { 	 _context._reportObserved(this);   } 	/// ReactiveContext   void _reportObserved(Atom atom) {     final derivation = _state.trackingDerivation;  /// 取出当前正在执行的reactions or computeds 	     if (derivation != null) {       derivation._newObservables.add(atom);  /// 将当前atom绑进derivation里       if (!atom._isBeingObserved) {       /// 如果atom之前并没有被加入观察,则执行此处         atom           .._isBeingObserved = true           .._notifyOnBecomeObserved();	/// 通知Observable 的所有listener - 其变为被观察状态       }     }   } 
上面可以看出,atom被加入到当前reaction(derivation)的监听集合里,即reaction持有了atom,但是atom改变时是需要通知到reaction的,继续看下面
_$valueAtom.reportChanged()1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 /// Atom void reportChanged() {    _context      ..startBatch()   /// batch计数+1 ,记录当前batch的深度,用来追踪如action执行的深度      ..propagateChanged(this)	/// 通知注册在atom里的observer(即Derivation)数据改变      ..endBatch();  /// 执行完毕,batch计数-1并检查batch执行深度是否归0,此处是做了层优化  }    /// ReactiveContext  void propagateChanged(Atom atom) {   ...    atom._lowestObserverState = DerivationState.stale;    for (final observer in atom._observers) {      if (observer._dependenciesState == DerivationState.upToDate) {        observer._onBecomeStale();  /// 通知所有注册的即Derivation数据改变      }      observer._dependenciesState = DerivationState.stale;    }  }    void endBatch() {    if (--_state.batch == 0) { /// 优化:当前执行改变的层次没回归0时,跳过最终的reaction响应,只有全部执行完毕才走下面的逻辑 (个人理解:因为是单线程,此处考虑的应该是递归情况,如action里再调用action)      runReactions();       /// 通知挂起的reactions 数据改变      ///  List<Reaction> pendingReactions = [];        /// The reactions that must be triggered at the end of a `transaction` or an `action`      for (var i = 0; i < _state.pendingUnobservations.length; i++) {      /// 这里处理断开连接的observations 如dispose掉        final ob = _state.pendingUnobservations[i]          .._isPendingUnobservation = false;        if (ob._observers.isEmpty) {          if (ob._isBeingObserved) {            // if this observable had reactive observers, trigger the hooks            ob              .._isBeingObserved = false              .._notifyOnBecomeUnobserved();          }          if (ob is Computed) {            ob._suspend();          }        }      }      _state.pendingUnobservations = [];    }  } 
 
基本上,_$Counter就是对@observable注解的变量扩展getter、setter方法,getter里将变量对应的atom绑进当前执行的derivation里去;在setter里去通知atom里的_observers集合。
@action注解的方法,则会被包含进_$_CounterActionController控制里,记录action执行情况
但是atom._observers里的元素是什么时候注册的,按照mobx的理念是在reaction里引用过Observable,则自动tracking,所以接下来看Observer
Observer flutter中作为UI的响应式组件,简单看下类图
                
                mobx_observer.png
             
如上图,StatelessObserverWidget extends StatelessWidget,框架主要通过ObserverWidgetMixin和ObserverElementMixin来扩展功能
ObserverWidgetMixin 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 mixin ObserverWidgetMixin on Widget {   String getName();   ReactiveContext getContext() => mainContext;   Reaction createReaction(     Function() onInvalidate, {     Function(Object, Reaction) onError,   }) =>       ReactionImpl(         getContext(),         onInvalidate,         name: getName(),         onError: onError,       ); } 
基本上就是扩展了 1) 创建Reaction  2) 获取mainContext 全局响应式上下文
ObserverElementMixin 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 mixin ObserverElementMixin on ComponentElement {   ReactionImpl get reaction => _reaction;   ReactionImpl _reaction;  /// 包裹的响应类   ObserverWidgetMixin get _widget => widget as ObserverWidgetMixin;   @override   void mount(Element parent, dynamic newSlot) {   /// 挂载Element 时 创建Reaction     _reaction = _widget.createReaction(invalidate, onError: (e, _) {       FlutterError.reportError(FlutterErrorDetails(         library: 'flutter_mobx',         exception: e,         stack: e is Error ? e.stackTrace : null,       ));     }) as ReactionImpl;     super.mount(parent, newSlot);   }   void invalidate() => markNeedsBuild();	/// Observable改变时会通知到这里 标脏   @override   Widget build() {     Widget built;     reaction.track(() {  /// 每次挂载上Element树上会启动reaction的track,在这里面建立在传入的build方法里(即Observer的build属性) 获取过的Observable的关联       built = super.build();	/// 调用外部传入的build方法 建立Widget子树     }); 	...     return built;   }   @override   void unmount() {   /// 卸载Element 时 卸载Reaction     reaction.dispose();     super.unmount();   } } 
接下来重点看reaction.track
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /// ReactionImpl   void track(void Function() fn) {     _context.startBatch();  /// batch次数+1     _isRunning = true;     _context.trackDerivation(this, fn);  /// 开始追踪这个derivation即此时的reaction     _isRunning = false;     if (_isDisposed) {       _context._clearObservables(this);   /// dispose的话 清理     }     if (_context._hasCaughtException(this)) {       _reportException(_errorValue._exception);       }     _context.endBatch();  /// 此处理操作完成   } 
进入_context.trackDerivation方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /// ReactiveContext    T trackDerivation<T>(Derivation d, T Function() fn) {     final prevDerivation = _startTracking(d);  /// 让mainContext开始追踪传入的derivation     T result;     if (config.disableErrorBoundaries == true) {       result = fn();     } else {       try {         result = fn();  /// 这里调用Observer里传入的build函数,里面会调用Observable的getter方法,上面提到的derivation就是这个d,所以atom会注册到这个d里面去         d._errorValue = null;       } on Object catch (e) {         d._errorValue = MobXCaughtException(e);       }     }     _endTracking(d, prevDerivation);  /// 结束追踪     return result;   } 
进入_startTracking(d)
1 2 3 4 5 6 7 8 9 10 /// ReactiveContext  Derivation _startTracking(Derivation derivation) {   final prevDerivation = _state.trackingDerivation;     _state.trackingDerivation = derivation;  /// 将传入的derivation赋值为当前正在追踪的,所以从这之后调用的Observable的getter方法里拿到的都是它   _resetDerivationState(derivation); /// 重置derivation状态   derivation._newObservables = {};	/// 清空,方便之后的atom加入   return prevDerivation; } 
进入_endTracking(d, prevDerivation)
1 2 3 4 void _endTracking(Derivation currentDerivation, Derivation prevDerivation) {   _state.trackingDerivation = prevDerivation;   _bindDependencies(currentDerivation);  /// 绑定derivation依赖的Observables } 
进入_bindDependencies(currentDerivation)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 void _bindDependencies(Derivation derivation) {    final staleObservables =        derivation._observables.difference(derivation._newObservables);  /// 取出不一致的observable集合    final newObservables =        derivation._newObservables.difference(derivation._observables); /// 取出新的observable集合    var lowestNewDerivationState = DerivationState.upToDate;    // Add newly found observables    for (final observable in newObservables) {      observable._addObserver(derivation);   /// 关键点1 这里将此derivation添加到Observable的_observers集合里,即在这里实现了atom持有derivation      // Computed = Observable + Derivation      if (observable is Computed) {        if (observable._dependenciesState.index >            lowestNewDerivationState.index) {          lowestNewDerivationState = observable._dependenciesState;        }      }    }    // Remove previous observables    for (final ob in staleObservables) {      ob._removeObserver(derivation);    }    if (lowestNewDerivationState != DerivationState.upToDate) {      derivation        .._dependenciesState = lowestNewDerivationState        .._onBecomeStale();    }    derivation      .._observables = derivation._newObservables      .._newObservables = {}; // No need for newObservables beyond this point  } 
如上关键点1,将derivation里关联的observable拿到,并将derivation注入到每个observable里,这里为止实现了observable和derivation的双向绑定
Computed 该对象由@computed生成,充当Atom和Derivation的双重身份,即作为Atom给Observer等Reaction来观察,作为Derivation其方法里调用了其他的Atom,会监听其他的Atom的变化来触发自身的改变
看下自己定义的类
1 2 3 4 5 6 7 8 9 10 11 12 abstract class _Counter with Store {   @observable   int value = 0;   @action   void increment() {     value++;   }   @computed   int get testCmp => value + 1; } 
生成的counter.g.dart
1 2 3 4 5 6 7 8 mixin _$Counter on _Counter, Store {   Computed<int> _$testCmpComputed;   @override   int get testCmp =>       (_$testCmpComputed ??= Computed<int>(() => super.testCmp)).value;   ...      } 
可以看出,实际就是生成了一个Computed来包裹我们定义的testCmp getter方法,下面看Computed的实现
1 2 3 4 5 6 7 8 class Computed<T> extends Atom implements Derivation, ObservableValue<T> { 	factory Computed(T Function() fn, {String name, ReactiveContext context}) =>       Computed._(context ?? mainContext, fn, name: name);   Computed._(ReactiveContext context, this._fn, {String name})       : super._(context, name: name ?? context.nameFor('Computed'));       ... } 
可以看出,具备了Atom和Derivation的特性,构造函数里比Atom多持有了外部的传入的(即我们自己定义的)方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Computed<T> extends Atom implements Derivation, ObservableValue<T> { 	...   T _value;  /// 缓存的value    	 @override   T get value { 	...     if (!_context.isWithinBatch && _observers.isEmpty) {     /// 如果没在action or transaction里执行 并且 被其作为atom _observers内无观察者时       if (_context._shouldCompute(this)) {  /// 判断其是否需要重新计算新的值,因为涉及到以及缓存         _context.startBatch();         _value = computeValue(track: false);  /// 计算新的值 且不将自己作为derivation利用mainContext进行追踪         _context.endBatch();       }     } else {       reportObserved();		/// 自己作为atom 被reaction调用时,上报自己给derivation监听       if (_context._shouldCompute(this)) {         if (_trackAndCompute()) {		/// 开启reaction的追踪并计算新值           _context._propagateChangeConfirmed(this);		/// 标记其持有的_observers 的依赖状态为脏         }       }     } 	...     return _value;   }       @override   void _suspend() {     _context._clearObservables(this);     _value = null;  /// 挂起时清除_value缓存值   } 	... } 
以上代码片段重点三个方法:_context._shouldCompute、computeValue(track: false)、_trackAndCompute()
_context._shouldCompute
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 bool _shouldCompute(Derivation derivation) {     switch (derivation._dependenciesState) {       case DerivationState.upToDate:         return false;       case DerivationState.notTracking:       case DerivationState.stale:         return true;       case DerivationState.possiblyStale:         return untracked(() {           for (final obs in derivation._observables) {  /// 遍历其使用过的Atom             if (obs is Computed) {  /// 判断依赖的atom是否也是Computed,是的话需要处罚依赖去计算新的值               // Force a computation               if (config.disableErrorBoundaries == true) {                 obs.value;  /// 触发计算新的值               } else {                 try {                   obs.value;                 } on Object catch (_) {                   return true;                 }               }               if (derivation._dependenciesState == DerivationState.stale) {                 return true;               }             }           }           _resetDerivationState(derivation);              return false;         });     }     return false;   } 
computeValue(track: false)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 T computeValue({bool track}) {     _isComputing = true; 	...     T value;     if (track) {       value = _context.trackDerivation(this, _fn); /// 让computed作为derivation身份,调用_fn前利用ReactiveContext开启tracking模式     } else { 		...         value = _fn();  /// 计算获取新的值 		...     } 	...     _isComputing = false;     return value;   } 
_trackAndCompute()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 bool _trackAndCompute() {     final oldValue = _value;     final wasSuspended = _dependenciesState == DerivationState.notTracking;     final newValue = computeValue(track: true);  /// 计算新值通知开启ReactiveContext的追踪     final changed = wasSuspended ||         _context._hasCaughtException(this) ||         !_isEqual(oldValue, newValue);     if (changed) {       _value = newValue;  /// 赋新值     }     return changed;   } 
总结 优点:
observer的组件真正实现按需更新,只有监听的数据发生变化,它才会re-render 
具备Computer计算属性机制,无引用时会自动回收 
使用注解省去了notify等模板代码,简洁 
mobx耦合性更低 
 
缺点:
store过多导致无法统一数据源,管理是个问题 
没有时间回溯能力,因为数据只有一份引用 
缺乏中间件机制有效支持