百瓶技能团队\color{#FBBC05}{百瓶技能团队} 大众号@百瓶技能\color{#FBBC05}{大众号 @ 百瓶技能}


「这是我参加11月更文挑战的第3天,活动概况检查:2021终究一次更文挑战」
「百瓶 App」(各市场搜索「百瓶」体会 )在 2019 年 11 月开端接入 Flutter 时,就选定了闲鱼的 Fish Redux 作为状况管理计划。经过近两年的迭代,现已完结了 80 个以上的 Page 级功用,积累了丰厚的运用经验。虽然 GitHub1 迭代更新较少,但是它在 2021-05-18 对外宣告正在进行 「2.0 架构的演进2」以及最近释放的 「Flutter Fish_Redux 3.0起航!3」,阐明内部仍是坚持在事务中运用并且对结构进行继续优化的。
本文首要论述 Fish Redux 两大方面的常识:
- 简略介绍中心概念以及依据 Fish Redux1 的「最佳」研制流程;
- 深化分析装备式拼装。
(补白:1. 阅览本文需求对 Flutter(v1.17.1) 和 Fish Redux(v0.3.7)(或者 Redux4)有简略的了解;2. 文中的很多概念,比方 Redux、Fish Redux 等的详细介绍链接都会共同放到文末「参阅」部分)。
中心概念
- 顾名思义:源自 阿里巴巴闲鱼(Fish)技能团队,站在巨人 Redux 的肩膀上,比方 State、Action、Reducer、Store、Middleware 等概念和 Redux 完全共同。
- 青出于蓝:处理了 Redux「会集」 和「分治」间的矛盾,并且由结构主动完结从细粒度的 Reducer 到 主 Reducer 的合并进程。
- 组件三要素:
Component = View + Effect(可选) + Reducer(可选) + Dependencies(可选):- View(UI 视图):完全由数据驱动,担任 Dispatch 工作(Effect 和 Reducer 详细完结),组件依靠经过
ViewService标准化调用; - Effect:处理 副作用(非修改数据的行为,包含生命周期相关的回调);
- Reducer:修改数据,并以扁平化的方式告诉组件刷新;
- Dependencies:表达组件之间的依靠关系。
- View(UI 视图):完全由数据驱动,担任 Dispatch 工作(Effect 和 Reducer 详细完结),组件依靠经过
「最佳」研制流程
假设需求完结下图 UI 的页面研制,ProtocolBuffer5(没接触过的直接了解为 API 文档即可)也现已规划结束。
那么,依据 Fish Redux 的最佳研制流程是怎么样的?
简略三步完结复杂页面的协同研制:
-
首要,进行组件拆分:拆分为五个大的组件(如图框所示,红 – profiles_component、绿 – malls_components、黄 – wallets_component、紫 – banners_component、蓝 – tools_component)。因为 Fish Redux 良好的分治策略,这时候完全可以分配给五个同学分别去完结单组件的开发(此时整个页面的目录结构如下图)。

-
其次,五位同学进行单组件的开发(以 蓝 – tools_component 为例):
-
state.dart:结合 ProtocolBuffer5 和 UI ,界说 State 结构; -
reducer.dart和action.dart:分析 state 的哪些数据会被改动,界说好相应的 Action 和 Reducer; -
effect.dart和action.dart:分析有哪些 副作用 工作响应(比方 请求数据、页面跳转等),界说好相应的 Action 和 Effect; -
view.dart:视图完结; -
component.dart:装备拼装,这一步一般由 插件6 主动生成了,当然 「最佳实践」 主张删去没有用到的模块(比方很多组件的dependencies)。
-
-
终究,Page 级拼装(后文会结合源码深化分析):
-
user_home_page/state.dart:1. 以子组件的 State(比方ProfilesState和ToolsState)为中心界说 State;2. 树立 State 的 Connector。 -
user_home_page/page.dart:装备拼装整个页面。
-
装备拼装
Fish Redux 经过 声明式装备 来将三大中心要素(View、Reducer、Effect)和依靠的子项 dependencies(子组件、middleware、adapter)完结主动拼装。 并且大部分代码都可以经过编辑器的 插件6 主动生成,仅有需求手动编写的便是
dependencies部分。这是非常重要的一个优点,但是业界讲得比较少。 补白:装备拼装的代码跟 FishRedux Example 基本共同,可以检查相关代码 7 加深了解。
接下去,将重点论述装备拼装的两个最中心的流程:注册 和 初次页面烘托。
注册
connecrtExtraStore 首要是完结一些大局状况的链接,重点看一下 UserHomePage() 部分。
UserHomePage() 「类图」
-
UserHomePage:自身不需求新增任何特点或办法,按照固定范式调用 超类 相关办法完结 「页面级」 的拼装,并且在注册时对应一个仅有路由。 -
fish_redux Page():-
InitState<T, P> _initState:页面初始状况,也是 Page 特有且必要的特点。 -
Widget buildPage(P param):初度页面烘托调用(后文会详细论述)。
-
-
fish_redux Component:-
ViewBuilder<T> _view:保护 View 层(buildView特点)。
-
-
fish_redux Logic:保护 reducer、 effect、 dependencies(所有的依靠子组成)等特点,中心逻辑处理。
dependencies
dependencies承受两个参数(代码见上文图):
adapter:为了处理 list 相关的性能问题,list 相关组件推荐运用;slots:页面(或组件)依靠的子组件,这是咱们重点要了解的部分。
UHPComponentNames.tools: ToolsConnector() + ToolsComponent()
-
UHPComponentNames.tools:依靠的姓名,String类型表明(最佳实践主张提成一个常量,而不是直接用一个 String)。 -
ToolsConnector():Tools 自己管理 State,经过 ToolsConnector 与 Page State 树立链接,Page State 完全不关心 toolsState 详细有哪些特点(高内聚低耦合)!
-
ToolsComponent():继承自Component,除了没有InitState和middleware相关(包含viewMiddleware、effectMiddleware和adapterMiddleware),其他跟 Page 的拼装没有差异。 -
ToolsConnector() +:追溯到ConnOp的 mixins –ConnOpMixin里重载了 「加号」,终究创立了一个_Dependent(redux_component/dependent.dart1) 实例(_Dependent<K, T>(connector: connector, logic: logic))。
_Dependent 的实例化,中心是创立生成 subReducer = connector.subReducer(logic.createReducer()) (下文「createReducer」相关章节会详细论述 reducer 的创立进程):

-
logic.createReducer():终究调用abstract class Logic的createReducer完结 自身 和 子组件 的 reducer 组合; -
connector.subReducer(logic.createReducer()):copy 回来一个新的 Reducer。
至此,Page 依据 state、effect、reducer、view 以及 dependencies 完结了实例化的整个进程。
初次页面烘托
当咱们打开 UserHomePage 时,会履行如下 routes.buildPage(即 类 Page 的 buildPage 办法),承受两个参数分别为 路由名和传入该页面的参数:

Class Page – Method buildPage
-
protectedWrapper: 默认回来_PageWidget, 也支撑自界说的包装(UserHomePage中传入特点wrapper,用的较少不用过多重视)。 - ❗️
_PageWidget: 本质上是一个StatefulWidget8,页面烘托的最中心部分。 - Lifecycle:Fish Redux 中默认的所有生命周期本质上来源于 Flutter Stateful Widget 的生命周期,Reducer 的生命周期和页面是共同的(
initState->didChangeDependencies->build……)。
_PageWidget
重点看一下 _PageWidget() 的整个流程(中心要素类图):

_PageWidget() 中 initState() 和 build() 相关的履行进程:

_PageWidget() – initState 中最重要的 createStore 的操作:
-
_initState(param): UserHomePage 中界说的initState在这里调用,承受路由参数对 State 进行初始化操作。 -
createReducer()进程中最中心的是combineReducers:
- 入参
[protectedReducer, protectedDependenciesReducer]: 1.protectedReducer便是咱们自己在reducer.dart文件中界说的buildReducer(); 2.protectedDependenciesReducer指的便是 依靠的子组件的 reducer,也是经过类似combineReducers的方式生成的(后文「createReducer – 生成子组件的 Reducer」部分再来看一下这个进程 )。 -
combineReducers:会做一些 reducer 的判空过滤,终究回来一个 colsure —— Reducer,在后续的 dispatch 相关操作时会履行。
- 入参
createReducer – 生成子组件的 Reducer
-
slots便是咱们在page.dart中界说的依靠子组件,createReducer()中经过循环遍历创立子组件(createSubReducer())的reducer列表,终究经过上文中相同的combineReducers以及combineSubReducers把 reducer 结合起来。 -
createSubReducer()终究是履行connector.subReducer(logic.createReducer())(redux_component/dependent.dart): -
combineReducers与上文共同,combineSubReducers中心终究仍是会调用 上文中的subReducer。
_PageWidget() – build() 相关操作
build() 终究调用链路会到 ComponentWidget, 也是一个 StatefulWidget,首要做了两件工作:
-
void initState():依据 store、bus 等创立一个 context,这个 context 会在整个页面周期中运用。比方页面中烘托子组件的操作 ——viewService.buildComponent('your-component-name')。 -
Widget build(BuildContext context): 真正创立视图的地方
以上便是 Fish Redux 整个主动装备拼装的进程,也简略说了下初次烘托的部分。
终究
源码解析部分并没有把所有细节都论述,如果感兴趣的朋友欢迎一起探讨。
有任何问题欢迎重视 「百瓶技能」大众号后发消息发问,会第一时间回复。
更多精彩请重视咱们的大众号“ 百瓶技能 ”,有不定期福利呦!
参阅
Footnotes
-
GitHub Fish Redux 源码 (2019-03-06 开源)github.com/alibaba/fis… ↩ ↩2 ↩3
-
闲鱼技能:Flutter Fish Redux 架构演进 2.0 (2021-05-18)mp.weixin.qq.com/s/8vFDLq3Wa…) ↩
-
Flutter Fish_Redux 3.0起航!:mp.weixin.qq.com/s/YYyU2yoM6… ↩
-
Redux redux.js.org ↩
-
Google Protocol Buffers: developers.google.com/protocol-bu… ↩ ↩2
-
Visual Studio Code Fish Redux Template Extension: marketplace.visualstudio.com/items?itemN… ↩ ↩2
-
Fish Redux 官方比如:github.com/alibaba/fis… ↩
-
Flutter StatefulWidget: api.flutter.dev/flutter/wid… [9]: Fish Redux 官方文档:github.com/alibaba/fis… ↩











