“This is the third day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021.”
When The App started to connect Flutter in November 2019, it selected Fish Redux as the state management solution. After nearly two years of iteration, more than 80 page-level functions have been completed and rich experience has been accumulated. Although GitHub2 has fewer iterations, its announcement on 2021-05-18 that it is working on “Evolution 3 of the 2.0 architecture” and the recent release of “Flutter Fish_Redux 3.0 launch! 10” shows that it is still in business and continuously optimizing the framework.
This paper mainly expounds the knowledge of Fish Redux in two aspects:
- A brief introduction to the core concepts and the “best practice” development process based on Fish Redux2;
- An in-depth look at configuration assembly.
Note: 1. Reading this article requires preparation for Flutter(V1.17.1) and Fish Redux(v0.3.7) (or Redux)1) Have a simple understanding; 2. Many concepts in this paper, such as Redux, Fish Redux and other detailed introduction links will be unified in the “Reference” section at the end of the article).
The core concept
- As the name implies: from Alibaba Fish technical team, standing on the shoulder of giant Redux, such as State, Action, Reducer, Store, Middleware and other concepts are completely consistent with Redux.
- It solves the contradiction between “focus” and “divide and conquer” of Redux, and automatically completes the merging process from fine-grained Reducer to main Reducer by the framework.
- Three components:
Component = View + Effect(optional) + Reducer(optional)
:- View (UI View) : fully driven by data, responsible for Dispatch events (Effect and Reducer), component dependencies pass
ViewService
Standardized call; - Effect: Handles side effects (the behavior of non-modifying data, including life-cycle related callbacks)
- Reducer: Modify data and inform components to refresh in a flat way;
- Dependencies: Describes the Dependencies between components.
- View (UI View) : fully driven by data, responsible for Dispatch events (Effect and Reducer), component dependencies pass
The “best” R&D process
ProtocolBuffer4 is already designed, assuming that the UI shown below needs to be developed.
So, what is the best development process for Fish Redux?
Three simple steps to complete collaborative research and development of complex pages:
- First, do component splitting: Broken down into five large components (as shown in the box, Red-profiles_component, green-malls_Components, yellow-Wallets_Component, purple-banners_Component, blue-tools_Component). Due to Fish Redux’s good divide-and-conquer strategy, five students could be assigned to complete the development of a single component.The directory structure of the entire page is shown below).
- Secondly, five students developed a single component (blue-tools_Component as an example):
state.dart
: combining ProtocolBuffer4And UI, define the State structure;reducer.dart
和action.dart
: Analyze which data of state will be changed and define corresponding actions and Reducer;effect.dart
和action.dart
: Analyze the side effects of event responses (such as request data, page jump, etc.) and define corresponding actions and effects;view.dart
: View implementation;component.dart
: Configuration assembly, this step is usually done by plug-ins6It is automatically generated, but of course “best practice” suggests removing unused modules (such as those of many components)dependencies
).
- Finally, page-level assembly (more on the source code below):
user_home_page/state.dart
: 1. Use the State of the child component (e.gProfilesState
和ToolsState
) define State for the core; 2. Establish State Connector.user_home_page/page.dart
: Configures the entire page.
Configure assembly
Fish Redux uses declarative configuration to automatically assemble the three core elements (View, Reducer, Effect) and dependencies (child components, Middleware, adapter).
Most of the code is automatically generated through plug-in 6 of the editor; the only thing you need to write manually is the Dependencies section. This is a very important advantage, but one that is rarely discussed in the industry.
Note: The code for configuring the assembly is basically the same as FishRedux Example. See code 5 for further understanding.
Next, I’ll focus on the two core processes of configuration assembly: registration and first page rendering.
registered
One line of code completes the user center page registration.
ConnecrtExtraStore basically does some global state linking, focusing on the UserHomePage() section.
UserHomePage()
“Class”
UserHomePage
: Does not need to add any attributes or methods, according to the fixed paradigm call superclass related methods to complete the “page level” assembly, and at the time of registration corresponding to a unique route.fish_redux Page()
:InitState<T, P> _initState
: The initial state of the Page, which is a page-specific and necessary property.Widget buildPage(P param)
: The first page render call (more on that later).
fish_redux Component
:ViewBuilder<T> _view
: Maintain View layer (buildView
Properties).
fish_redux Logic
Maintain reducer, effect, dependencies (all dependent sub-components) and other attributes, and process core logic.
dependencies
Dependencies takes two parameters (see the code in figure above) :
adapter
: To solve list-related performance problems, list-related components are recommended.slots
: The child components on which the page (or component) depends, and this is the important part to understand.
UHPComponentNames.tools: ToolsConnector() + ToolsComponent()
UHPComponentNames.tools
: dependency name,String
Type indication (best practice suggests a constant rather than a String directly).ToolsConnector()
Tools manages State and links with Page State via ToolsConnector. Page State doesn’t care what properties toolsState has!
ToolsComponent()
: inherited fromComponent
Except that noInitState
和middleware
Relevant (includingviewMiddleware
,effectMiddleware
和adapterMiddleware
), the other assembly is no different from Page.ToolsConnector() +
: back to theConnOp
Mixins –ConnOpMixin
Overrides the plus sign and eventually creates one_Dependent
(redux_component/dependent.dart2() example_Dependent<K, T>(connector: connector, logic: logic)
).
_Dependent
The instantiation of the, the core is create buildsubReducer = connector.subReducer(logic.createReducer())
(The following section of “createReducer” will elaborate on the reducer creation process):
logic.createReducer()
: Final callabstract class Logic
的createReducer
Complete the Reducer combination of itself and sub-components;connector.subReducer(logic.createReducer())
: copy Returns a new Reducer.
So far, Page completes the whole process of instantiation based on State, Effect, Reducer, View and Dependencies.
First page render
When we open upUserHomePage
Is executed as followsroutes.buildPage
(that is, the classPage
的 buildPage
Method), takes two parameters as the route name and the parameters passed to the page:
Class Page – Method buildPage
protectedWrapper
: Returns by default_PageWidget
, also supports custom wrappers (UserHomePage
An incoming attribute inwrapper
, less need not pay too much attention).- ❗ ️
_PageWidget
: Essentially oneStatefulWidget
8Page renderedHeart and soul. - 💡 Lifecycle: all life cycles in Fish Redux were essentially derived from the Lifecycle of the Flutter Stateful widgets, and the Reducer Lifecycle was consistent with the page (
initState
->didChangeDependencies
->build
……) .
_PageWidget
Focus on_PageWidget()
The entire process (core elements class diagram) :
_PageWidget()
中 initState()
和 build()
Related execution process:
_PageWidget()
– initState
The most important of allcreateStore
Operation:
_initState(param)
: defined in UserHomePageinitState
Called here to initialize State with route parameters.createReducer()
The core of the process iscombineReducers
:
- The ginseng
[protectedReducer, protectedDependenciesReducer]
: 1.protectedReducer
It’s usreducer.dart
Defined in the filebuildReducer()
; 2.protectedDependenciesReducer
Reducer refers to the reducer of dependent subcomponents, which is also passed similarlycombineReducers
(see this process in the following section of “createReducer – createReducer of sub-components”). combineReducers
Some empty filtering will be done on reducer, and finally a colsure — reducer will be returned, which will be executed in subsequent dispatch related operations.
CreateReducer – Generates a Reducer of subcomponents
slots
Is that we arepage.dart
Dependency subcomponents defined in,createReducer()
Create child components by looping through thecreateSubReducer()
)reducer
List finally through the same abovecombineReducers
As well ascombineSubReducers
Combine the Reducer.createSubReducer()
Ultimately it’s executionconnector.subReducer(logic.createReducer())
(redux_component/dependent. Dart) :logic.createReducer()
It’s really executionlogic.dart
In thecreateReducer()
.The subReducer (...).
Eventually performMutableConn
的subReducer()
:get
Above:ToolsConnector
Parent component state connector in their own definition, so that the child component to obtain the corresponding state data;- Generate the new state from the action and props and compare it to the old state;
- Clone a new return if there is a change, and notify the view to change the corresponding state, otherwise return the current state.
combineReducers
Consistent with the above,combineSubReducers
The core will eventually call the abovesubReducer
。
_PageWidget()
– build()
The relevant operation
The build() final call link goes to ComponentWidget, which is also a StatefulWidget that does two things:
void initState()
: Creates a context based on store, bus, etc. This context will be used throughout the page cycle. For example, rendering a child component in a pageviewService.buildComponent('your-component-name')
.Widget build(BuildContext context)
: Where the view is actually created
That’s how Fish Redux went through the automatic configuration and assembly process, with a brief introduction to the first rendering.
The last
The source code analysis part does not elaborate all the details, if interested in friends welcome to discuss.
If you have any questions, please pay attention to the “Baipin Technology” public account and send a message to ask questions. We will reply as soon as possible.
More exciting, please pay attention to our public number “100 bottle technology”, there are not regular benefits!
reference
- GitHub Fish Redux 下 载 github.com/alibaba/fis… ↩
- Idle Fish technology: Flutter Fish story architecture evolution (2021-05-18) 2.0 mp.weixin.qq.com/s/8vFDLq3Wa…). ↩
- The Flutter Fish_Redux 3.0 launches! : mp.weixin.qq.com/s/YYyU2yoM6… ↩
- Redux redux.js.org↩
- Google Protocol Buffers: developers.google.com/protocol-bu… ↩
- The Visual Studio Code Fish story Template Extension: marketplace.visualstudio.com/items?itemN… ↩
- Fish Redux official example: github.com/alibaba/fis… ↩
- Flutter StatefulWidget: API. Flutter. Dev/Flutter/wid… ↩