Redux是一个Flutter状态管理工具。实现并不复杂,其核心是一个简单的观察者模式。我们从 观察者 和 被观察者 两个角度来分析 Redux
被观察者 Store/State
被观察者 明显是 Store 和 State 。 State 是状态的 model类 。 Store 是 State 的持有者。
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
| class Store<State> { Reducer<State> reducer;
final StreamController<State> _changeController; State _state; List<NextDispatcher> _dispatchers;
Store( this.reducer, { State initialState, List<Middleware<State>> middleware = const [], bool syncStream = false, bool distinct = false, }) : _changeController = StreamController.broadcast(sync: syncStream) { _state = initialState; _dispatchers = _createDispatchers( middleware, _createReduceAndNotify(distinct), ); }
NextDispatcher _createReduceAndNotify(bool distinct) { return (dynamic action) { final state = reducer(_state, action);
if (distinct && state == _state) return;
_state = state; _changeController.add(state); }; }
dynamic dispatch(dynamic action) { return _dispatchers[0](action); }
Stream<State> get onChange => _changeController.stream; }
|
当一个 Store 创建时,会实例化一个 _changeController ,并将 middleware 和 reducer 打包合并成 _dispatchers 集合。
注意看 _createReduceAndNotify 方法, 当每一个 action 发送到 Store 时,会交给 reducer 处理,并将新的 state 给 add 到 _changeController 里。这样就完成了状态的更新。。
是不是很简单。。。
观察者
Redux 里观察者是 StoreConnector 。
但是得先提一下 StoreProvider , StoreProvider 是初始化和存储 Store 的 Widget 。
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 StoreProvider<S> extends InheritedWidget { final Store<S> _store;
const StoreProvider({ Key key, @required Store<S> store, @required Widget child, }) : assert(store != null), assert(child != null), _store = store, super(key: key, child: child);
static Store<S> of<S>(BuildContext context, {bool listen = true}) { final type = _typeOf<StoreProvider<S>>(); final provider = (listen ? context.inheritFromWidgetOfExactType(type) : context .ancestorInheritedElementForWidgetOfExactType(type) ?.widget) as StoreProvider<S>;
if (provider == null) throw StoreProviderError(type);
return provider._store; }
static Type _typeOf<T>() => T;
@override bool updateShouldNotify(StoreProvider<S> oldWidget) => _store != oldWidget._store; }
|
StoreProvider 也很简单,就是一个典型的 InheritedWidget 。
现在来看 StoreConnector ,
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 StoreConnector<S, ViewModel> extends StatelessWidget { const StoreConnector({ Key key, @required this.builder, @required this.converter, this.distinct = false, this.onInit, this.onDispose, this.rebuildOnChange = true, this.ignoreChange, this.onWillChange, this.onDidChange, this.onInitialBuild, }) : assert(builder != null), assert(converter != null), super(key: key);
@override Widget build(BuildContext context) { return _StoreStreamListener<S, ViewModel>( store: StoreProvider.of<S>(context), builder: builder, converter: converter, distinct: distinct, onInit: onInit, onDispose: onDispose, rebuildOnChange: rebuildOnChange, ignoreChange: ignoreChange, onWillChange: onWillChange, onDidChange: onDidChange, onInitialBuild: onInitialBuild, ); } }
|
可以看出来,StoreConnector 只是一个壳,实际的工作者是 _StoreStreamListener 。 StoreConnect 唯一做的工作就是调用 StoreProvider.of<S>(context)
给 _StoreStreamListener 的 store 赋值。
_StoreStreamListener 是一个 StatefulWidget
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 53
| class _StoreStreamListenerState<S, ViewModel> extends State<_StoreStreamListener<S, ViewModel>> {
@override void initState() { ...
latestValue = widget.converter(widget.store); _createStream();
super.initState(); }
@override Widget build(BuildContext context) { return widget.rebuildOnChange ? StreamBuilder<ViewModel>( stream: stream, builder: (context, snapshot) => widget.builder( context, latestValue, ), ) : widget.builder(context, latestValue); }
void _createStream() { stream = widget.store.onChange .where(_ignoreChange) .map(_mapConverter) .where(_whereDistinct) .transform(StreamTransformer.fromHandlers(handleData: _handleChange)); }
ViewModel _mapConverter(S state) { return widget.converter(widget.store); }
bool _whereDistinct(ViewModel vm) { if (widget.distinct) { return vm != latestValue; }
return true; }
void _handleChange(ViewModel vm, EventSink<ViewModel> sink) { ... latestValue = vm; ... sink.add(vm); } }
|
在 build 方法中 widget.rebuildOnChange 默认为 true 。
StreamBuilder 将 stream 转化为 widget 。
stream 就是对 widget.store.onChange (Store 里的 _changeController) 的监听。
需要说明的是, StoreConnector 只是在 Flutter Framework 基础上添加的额外的监听机制。
之前自己一直有个误区: 当 StoreConnector 的外部 Widget 执行 rebuild 之后, StoreConnector 可以控制 child 不 rebuild ,只要 vm 没有发生改变。
这显然不正确。有空可以看看 StreamBuilder 的源码。
Action 事件的执行
1 2 3 4 5
| class Store { dynamic dispatch(dynamic action) { return _dispatchers[0](action); } }
|
。。。很简单, Store.dispath 从 _dispatchers 的第一个位置开始分发事件。。