Flutter实践:深入 Flutter 的状态管理方式(3)——Redux与旅途小结

栏目: IOS · Android · 发布时间: 5年前

内容简介:至此这已经是 Flutter 状态管理方式文章的最后一篇,之后我将将他们应用在实际项目中开发并将值的学习的项目开源出来。对于其中讲解可能有点浅尝则止,因为给出的实例相对简单,但相信聪明的程序员都会有自己的学习方法,你可以从给出的实例结合自己的所学引深出更好的设计方法。同时要送给大家的建议是:请在需要这些状态管理方式时使用它,我见过不少的开发者都有用大刀砍白菜的意思,这并不是一个好习惯,你会发现这些状态管理方式有时候不但不会使开发简单,其实还会加大代码量,使其变得复杂,对于如何选择,这里还不够说清楚,希望你们

至此这已经是 Flutter 状态管理方式文章的最后一篇,之后我将将他们应用在实际项目中开发并将值的学习的项目开源出来。对于其中讲解可能有点浅尝则止,因为给出的实例相对简单,但相信聪明的 程序员 都会有自己的学习方法,你可以从给出的实例结合自己的所学引深出更好的设计方法。

同时要送给大家的建议是:请在需要这些状态管理方式时使用它,我见过不少的开发者都有用大刀砍白菜的意思,这并不是一个好习惯,你会发现这些状态管理方式有时候不但不会使开发简单,其实还会加大代码量,使其变得复杂,对于如何选择,这里还不够说清楚,希望你们都能找到自己的管理应用程序的方式。

所有实例:

github 地址: https://github.com/MeandNi/Flutter_StateManagement

博客地址:https://meandni.com/

Githib: https://github.com/MeandNi/

欢迎一起交流学习!

下面请看正文:

Redux 由 Facebook 2015年提出,是基于 Flux 理念实现的一个响应式框架的状态管理方式,最早应用于 React 中,而后 React Native 、 Flutter 等多个框架也同样可以使用。

学习 Redux 之前,请了解 Redux 所能做到的事情:

  • 单一状态来源:整个应用程序的状态存储在单个的对象树中。
  • 状态只读:更改状态的唯一方法是发出一个 action(一个描述发生什么事件的对象)。
  • 使用纯函数更改状态:通过 reducers,状态知道如何通过操作进行改变,reducers便是一个纯函数。
Flutter实践:深入 Flutter 的状态管理方式(3)——Redux与旅途小结

如果你用过 React ,相信你对上面的概念已经很清晰了,没使用过?也 OK,下面慢慢道来….

整体的思路:所有状态存放在 store 中,Redux 将 store 内所有状态放入对应的组件中呈现在 Ui 上,用户与 UI 交互(如点击)发起一个 action(一个描述行为的对象),store 可判别 action类型并作用相应的 reducer(操作改变状态的纯函数),reducer 完成相应改变后将数据放到全局的 store 中,实现改变。

Flutter实践:深入 Flutter 的状态管理方式(3)——Redux与旅途小结

思路简单,描述起来蛮复杂,其实它的目的就是实现代码作用域的分离。

那么如何让将以上描述应用于实际的应用程序中呢?

redux 实现计数器应用

其中的实现与 ScopedModel 很相似, 抓住两个要点,如何在 UI 中呈现以及如何 发起 action 改变状态。

我们首先定义 一个全局状态 AppState:

@immutable
class AppState {
  final counter;
  AppState(this.counter);
}

里面有一个 counter 变量用于计数。

Action

如前面所述,State 的变化,会导致 UI 的变化。但是,用户接触不到 State,只能接触到 UI。所以,State 的变化必须是 UI 导致的。Action 就是 UI 发出的通知,表示 State 应该要发生变化了。

我们这里有一个促使 counter 增加的 action:

enum Actions { Increment }

reducer

Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。

Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

AppState reducer(AppState prev, action) {
  if (action == Actions.Increment) {
    return new AppState(prev.counter + 1);
  }
  return prev;
}

reducer 中判断了 action 时 Increment 这一类型,将一个新的 AppState 返回到 store。

在 UI 中呈现(StoreConnector)

首先初始化状态:

final store = new Store(reducer, initialState: new AppState(0));

然后显示状态:

new StoreConnector(
  converter: (store) => store.state.counter,
  builder: (context, counter) => new Text(
    '$counter',
    style: Theme.of(context).textTheme.display1,
  ),
)

通过 converter 属性拿到 state 中的 counter 属性。

然后传入 builder 应用在组件中。

发起 action 改变状态

new StoreConnector(
    converter: (store) {
      return () => store.dispatch(Actions.Increment);
    },
    builder: (context, callback) => new FloatingActionButton(
      onPressed: callback,
      tooltip: 'Increment',
      child: new Icon(Icons.add),
    ), 
),

同样是使用 StoreConnector,然而这次通过 converter 拿到的是一个 store.dispatch(Actions.Increment)store.dispatch() 是 View 发出 Action 的唯一方法。而后在组件中调用该回调方法即可。

完整代码

完整代码被放在一个文件中: 样例代码

Redux 应用在 ShoppingCart: 样例代码

Flutter实践:深入 Flutter 的状态管理方式(3)——Redux与旅途小结
Flutter实践:深入 Flutter 的状态管理方式(3)——Redux与旅途小结

将 Redux 用于更复杂的应用中

在复杂的应用中我们可以将应用程序中的 reducer 根据业务类型分离,例如用户信息、产品信息等不同业务的操作分离到单独的模块,

Flutter实践:深入 Flutter 的状态管理方式(3)——Redux与旅途小结

而后将其合并:

Flutter实践:深入 Flutter 的状态管理方式(3)——Redux与旅途小结

实现上看的分离后,又可只将相应业务的数据放到相应业务根 widget(其子组件的所有数据和操作来自该根组件)

我们将需要的数据及操作到一个对象中,传递到组件中:

class DeviceFragment extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: new StoreConnector<AppState, _ViewModel>(
          converter: _ViewModel.fromStore,
          builder: (context, vm) {
            return DeviceList(
              devices: vm.devices,
              onStateChanged: vm.onStateChanged,
              onRemove: vm.onRemove,
              onUndoRemove: vm.onUndoRemove,
            );
          }),
    );
  }
}

class _ViewModel {
  final List<Device> devices;

  // final bool loading;
  final Function(Device) onStateChanged;
  final Function(Device) onRemove;
  final Function(Device) onUndoRemove;

  _ViewModel({
    @required this.devices,
    // @required this.loading,
    @required this.onStateChanged,
    @required this.onRemove,
    @required this.onUndoRemove,
  });

  static _ViewModel fromStore(Store<AppState> store) {
    return _ViewModel(
      devices: store.state.devices,
      // loading: store.state.isLoading,
      onStateChanged: (device) {
        store.dispatch(editItem(device.copyWith(state: !device.state)));
      },
      onRemove: (device) {
        store.dispatch(deleteDevice(device));
      },
      onUndoRemove: (device) {
        store.dispatch(AddDeviceAction(device));
      },
    );
  }
}

这样使得产生模块化管理的思想!(以上实例来自正在开发的一个真实项目,目前还未开源。)

同时,在实际的应用程序中,你一定需要在程序启动初期来加载来自云端或者数据本地的数据,你可以在入口的页面中接受一个加载数据的函数,放入 initState 函数中。


以上所述就是小编给大家介绍的《Flutter实践:深入 Flutter 的状态管理方式(3)——Redux与旅途小结》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

新机器的灵魂

新机器的灵魂

Tracy Kidder / 龚益、高宏志 / 机械工业出版社华章公司 / 2011-10 / 45.00元

计算机从1981年开始发生巨大的变化。《新机器的灵魂》完整地记录下了当时一家公司齐心协力把一种新的小型计算机推向市场的过程中所发生的一系列戏剧性的、充满戏剧色彩的、激动人心的故事。 本书以美国通用数据公司研制鹰电子计算机的全过程为主线,对美国计算机工业的发展和管理中鲜为人知的侧面,作了条理清晰、颇具诗情画意的描述。 你想知道一代新型计算机怎样诞生,精明干练而又富于幽默感的工程技术人员怎......一起来看看 《新机器的灵魂》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试