flutter_redux

flutter_redux和scoped_model都能很好的对我们的应用进行状态管理上一篇文章简单的介绍了scoped_model这篇文章介绍一下flutter_redux的使用和我自己的一些理解

先不说flutter_redux,这个概念前端开发的朋友应该都不会陌生,而对移动端的伙伴就比较陌生了,所以我查看了Redux的相关介绍其中有一个三大原则

单一数据源

整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。

State 是只读的

唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。

使用纯函数来执行修改

为了描述 action 如何改变 state tree ,你需要编写 reducers

说人话我的理解就是所有状态都在store中想要修改state就是要触发action,如何触发action呢,就是写方法就是reducers.
这样看来使用redux就很好管理我们的应用了我们把所有不同的状态定义成枚举也就是action然后,对应action定义很多改变状态的方法也就是reducers,当触发action的时候我们来执行方法从而改变状态

好的回到flutter_redux
既然加了redux用法应该是遵守三大原则的我们就用flutter最基础的Demo两个不同界面通过Redux共享一个信息

三大原则中第一个就是有一个唯一的store所以不用说,这个store一定在App的入口处,进行全局的管理

import 'package:redux/redux.dart';

void main() {
  final store =
  Store<CountState>(reducer, initialState: CountState.initState());
  runApp(MyApp(store: store))
};

看到这个Store有一些摸不清头脑那我们点进去一看究竟

Store(
    this.reducer, {
    State initialState,
    List<Middleware<State>> middleware = const [],
    bool syncStream = false,

    /// If set to true, the Store will not emit onChange events if the new State
    /// that is returned from your [reducer] in response to an Action is equal
    /// to the previous state.
    ///
    /// Under the hood, it will use the `==` method from your State class to
    /// determine whether or not the two States are equal.
    bool distinct = false,
  }) 

大家发现了一个很眼熟的东西this.reducer,那这个reducer是个什么东西再点进去看看

typedef State Reducer<State>(State state, dynamic action);

现在明白了我们需要自己定义一个state同时我们接受一个state和一个action然后返回一个新的state这个state还进行泛型的保护
那我们按部就班先定义一个状态类

class CountState{
  int _count;
  get count => _count;
  CountState(this._count);
  CountState.initState() : _count = 0;
}

然后我们定义一个action这个action前面已经提到了应该是一个enum,枚举里现在只有一个状态就是增加当然我们可以加入更多状态

enum Action{
  increment
}

然后我们实现reducers这个方法按照要求传入一个状态和一个action返回一个状态

CountState reducer(CountState state,action){
  //匹配Action
  if(action == Action.increment){
    return CountState(state.count+1);
  }
  return state;
}

好了准备工作完成那我们怎么在各个子控件控制器内拿到我们改变后的状态,同时使用改变后的数据或者再次改变呢flutter_redux给我们提供了一个叫StoreConnector的类

class StoreConnector<S, ViewModel> extends StatelessWidget {
  /// Build a Widget using the [BuildContext] and [ViewModel]. The [ViewModel]
  /// is created by the [converter] function.
  final ViewModelBuilder<ViewModel> builder;

  /// Convert the [Store] into a [ViewModel]. The resulting [ViewModel] will be
  /// passed to the [builder] function.
  final StoreConverter<S, ViewModel> converter;

  /// As a performance optimization, the Widget can be rebuilt only when the
  /// [ViewModel] changes. In order for this to work correctly, you must
  /// implement [==] and [hashCode] for the [ViewModel], and set the [distinct]
  /// option to true when creating your StoreConnector.
  final bool distinct;

  /// A function that will be run when the StoreConnector is initially created.
  /// It is run in the [State.initState] method.
  ///
  /// This can be useful for dispatching actions that fetch data for your Widget
  /// when it is first displayed.
  final OnInitCallback<S> onInit;

  /// A function that will be run when the StoreConnector is removed from the
  /// Widget Tree.
  ///
  /// It is run in the [State.dispose] method.
  ///
  /// This can be useful for dispatching actions that remove stale data from
  /// your State tree.
  final OnDisposeCallback<S> onDispose;

  /// Determines whether the Widget should be rebuilt when the Store emits an
  /// onChange event.
  final bool rebuildOnChange;

  /// A test of whether or not your [converter] function should run in response
  /// to a State change. For advanced use only.
  ///
  /// Some changes to the State of your application will mean your [converter]
  /// function can't produce a useful ViewModel. In these cases, such as when
  /// performing exit animations on data that has been removed from your Store,
  /// it can be best to ignore the State change while your animation completes.
  ///
  /// To ignore a change, provide a function that returns true or false. If the
  /// returned value is true, the change will be ignored.
  ///
  /// If you ignore a change, and the framework needs to rebuild the Widget, the
  /// [builder] function will be called with the latest [ViewModel] produced by
  /// your [converter] function.
  final IgnoreChangeTest<S> ignoreChange;

  /// A function that will be run on State change, before the Widget is built.
  ///
  /// This function is passed the `ViewModel`, and if `distinct` is `true`,
  /// it will only be called if the `ViewModel` changes.
  ///
  /// This can be useful for imperative calls to things like Navigator,
  /// TabController, etc. This can also be useful for triggering actions
  /// based on the previous state.
  final OnWillChangeCallback<ViewModel> onWillChange;

  /// A function that will be run on State change, after the Widget is built.
  ///
  /// This function is passed the `ViewModel`, and if `distinct` is `true`,
  /// it will only be called if the `ViewModel` changes.
  ///
  /// This can be useful for running certain animations after the build is
  /// complete.
  ///
  /// Note: Using a [BuildContext] inside this callback can cause problems if
  /// the callback performs navigation. For navigation purposes, please use
  /// [onWillChange].
  final OnDidChangeCallback<ViewModel> onDidChange;

  /// A function that will be run after the Widget is built the first time.
  ///
  /// This function is passed the initial `ViewModel` created by the [converter]
  /// function.
  ///
  /// This can be useful for starting certain animations, such as showing
  /// Snackbars, after the Widget is built the first time.
  final OnInitialBuildCallback<ViewModel> onInitialBuild;

  /// Create a [StoreConnector] by passing in the required [converter] and
  /// [builder] functions.
  ///
  /// You can also specify a number of additional parameters that allow you to
  /// modify the behavior of the StoreConnector. Please see the documentation
  /// for each option for more info.
  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的东西我们上能画UI下能拿状态

StoreConnector<CountState, int>(
              converter: (store) => store.state.count,
              builder: (context, count) {
                return Text(
                  count.toString(),
                  style: Theme.of(context).textTheme.display1,
                );
              },
            ),

通过converter拿到状态类使用状态类的属性

 floatingActionButton:StoreConnector<CountState,VoidCallback>(
        converter: (store) {
          return () => store.dispatch(Action.increment);
        },
        builder: (context, callback) {
          return FloatingActionButton(
            onPressed: callback,
            child: Icon(Icons.add),
          );
        },
      ),

通过converter触发我们定义好的action改变数字

最后

其实flutter_redux还有很多复杂的用法这里只是抛砖引玉给大家提供一个思路更多深入的东西我也会慢慢研究,然后进行记录.因为我是移动端出身个人感觉
flutter_redux过于繁琐,定义action包括实现reducer等很难受我还是更偏向使用scoped_model我觉得scoped_model相对简洁但是可读性没有flutter_redux好个人的一点见解,大家也可以说说自己对flutter_redux的理解,也欢迎拍砖.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容