Flutter 状态管理
前言
Flutter的很多灵感来自于React,它的设计思想是数据与视图分离,由数据映射渲染视图。所以在Flutter中,它的Widget是immutable的,
而它的动态部分全部放到了状态(State)中。于是状态管理自然便成了我们密切关注的对象
为什么需要状态管理
- 在我们一开始构建应用的时候,也许很简单。我们有一些状态,直接把他们映射成视图就可以了。这种简单应用可能并不需要状态管理。
2. 但是随着功能的增加,你的应用程序将会有几十个甚至上百个状态。这个时候你的应用应该会是这样
Wow,这是什么鬼。我们很难再清楚的测试维护我们的状态,因为它看上去实在是太复杂了!而且还会有多个页面共享同一个状态,
例如当你进入一个文章点赞,退出到外部缩略展示的时候,外部也需要显示点赞数,这时候就需要同步这两个状态。
这时候,我们便迫切的需要一个架构来帮助我们理清这些关系,状态管理框架应运而生。
状态管理框架概述
Flutter的状态管理框架目前知道的有以下
1.
redux
2.
Scoped Model
-
Scoped_model是一个dart第三方库,提供了让您能够轻松地将数据模型从父Widget传递到它的后代的功能。此外,它还会在模型更新时重新渲染使用该模型的所有子项。
它直接来自于Google正在开发的新系统Fuchsia核心Widgets 中对Model类的简单提取,作为独立使用的独立Flutter插件发布。
实现原理
3.
BLoC (Business Logic Componet)
-
BLoC是一种利用reactive programming方式构建应用的方法,这是一个由流构成的完全异步的世界。
-
用StreamBuilder包裹有状态的部件,streambuilder将会监听一个流
-
这个流来自于BLoC
-
有状态小部件中的数据来自于监听的流。
-
用户交互手势被检测到,产生了事件。例如按了一下按钮。
-
调用bloc的功能来处理这个事件
-
在bloc中处理完毕后将会吧最新的数据add进流的sink中
-
StreamBuilder监听到新的数据,产生一个新的snapshot,并重新调用build方法
-
Widget被重新构建
-
BLoC能够允许我们完美的分离业务逻辑!再也不用考虑什么时候需要刷新屏幕了,一切交给StreamBuilder和BLoC!和StatefulWidget说拜拜!!
-
BLoC代表业务逻辑组件(Business Logic Component),由来自Google的两位工程师 Paolo Soares和Cong Hui设计,并在2018年DartConf期间(2018年1月23日至24日)首次展示。点击观看Youtube视频。。
4.
Provide
- 和Scoped_model一样,Provide也是借助了InheritWidget,将共享状态放到顶层MaterialApp之上。底层部件通过Provier获取该状态,并通过混合ChangeNotifier通知依赖于该状态的组件刷新。
- Provide还提供了Provide.stream,让我们能够以处理流的方式处理数据
1. redux
假如你曾进行过react开发,也许你一下会想到Redux,flutter有类似redux的状态管理的库吗?答案是肯定的。
redux是什么
-
Redux是一种单向数据流架构,可以轻松开发,维护和测试应用程序
Store: 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。
State: Store对象包含所有数据。如果想得到某个时点的数据,就要对 Store 生成快照。这种时点的数据集合,就叫做 State
Action: 是一个对象。其中的type属性是必须的,表示 Action 的名称。其他属性可以自由设置
纯函数是函数式编程的概念,必须遵守以下一些约束。
- 不得改写参数
- 不能调用系统 I/O 的API
- 不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果
Redux三大原则
- 单一的数据来源(App统一的Store)
- 状态State是只读的(数据不能直接修改,只能用过约定的Action触发,Reduce修改)
- 数据改动须是纯函数(这些纯函数叫Reducer,定义了如何修改Store,由Action触发)
Rexdux(3.0.0):
- Redux(3.0.0)是作者用Dart把JS 的redux库实现了,它定义了Store,Action,Reduce,Middleware以及它们之间的行为关系。
flutter_redux(0.5.2):
- flutter_redux(0.5.2)作为工具类桥接Redux和Flutter,它提供了StoreProvider,StoreBuilder,StoreConnector这些组件,使我们在flutter中使用redux变的很简便
- StoreProvider - The base Widget. It will pass the given Redux Store to all descendants that request it.
- StoreBuilder - A descendant Widget that gets the Store from a StoreProvider and passes it to a Widget builder function.
- StoreConnector - A descendant Widget that gets the Store from the nearest StoreProvider ancestor, converts the Store into a ViewModel with the given converter function, and passes the ViewModel to a builder function. Any time the Store emits a change event, the Widget will automatically be rebuilt. No need to manage subscriptions!
使用redux
- 添加支持库
1 | dependencies: |
- 创建State
1 | import 'package:meta/meta.dart'; |
- 创建action
1 | ///第三步 创建Action |
- 创建reducer
1 | ///第四步 创建reducer |
- 创建store
1 | void main() { |
- 将Store放入顶层
1 | class MyApp extends StatelessWidget { |
- 在子页面中获取Store中的state
1 | Padding( |
- 发出action
1 | Expanded( |
redux进阶
redux中间件介绍:
-
Redux middleware 提供了一个分类处理 action 的机会。在 middleware 中,我们可以检阅每一个流过的 action,并挑选出特定类型的 action
进行相应操作,以此来改变 action。这样说起来可能会有点抽象,我们直接来看图,这是在没有中间件情况下的 redux 的数据流:
-
上面是很典型的一次 redux 的数据流的过程,但在增加了 middleware 后,我们就可以在这途中对 action 进行截获,并进行改变。
且由于业务场景的多样性,单纯的修改 dispatch 和 reduce 显然不能满足大家的需要,因此对 redux middleware 的设计理念是可以自由组合,
自由插拔的插件机制。也正是由于这个机制,我们在使用 middleware 时,我们可以通过串联不同的 middleware 来满足日常的开发需求,
每一个 middleware 都可以处理一个相对独立的业务需求且相互串联:
使用步骤:
- 创建一个产生中间件的工厂类,利用generate产生中间件
1 | ///第一步创建一个产生中间件的工厂类, |
- 通过new TypedMiddleware的方式创建中间件
1 | class LoggerMiddle extends MiddlewareFactory { |
- 把所有的中间件集合到一起
1 | ///第三步 把所有的中间件集合到一起 |
- 把所有的中间件都放到Store里面
1 | final store = Store<CountState>(reducers |
添加redux_thunk支持异步操作
- redux_thunk原理
1 | void thunkMiddleware<State>( |
- 创建一个ThunkAction类型的异步Action处理函数
1 | ///第一步 创建一个ThunkAction类型的异步Action处理函数 |
- 创建一个异步处理的中间件俩处理我们的Thunk类型的函数
1 | class ThunkMiddle extends MiddlewareFactory { |
- 一起放到中间件集合里面
1 | ///第三步 把所有的中间件集合到一起 |
状态持久化
添加redux_persist_flutter 或者自己把Store里面的State序列化到本地文件,然后启动的时候反序列化出来就可