主要介紹閑魚出品的fish redux基礎知識和使用,后續(xù)會有復雜應用場景分享。
flutter自帶demo
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Flutter Demo Home Page'),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('$_counter'),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
flutter的計數demo,方便后面對比。
redux
簡介Redux的流程

<figcaption>redux 簡介</figcaption>
簡單說就是用戶操作dispatcher(action),到reducer中處理相關數據和邏輯,存儲數據到store中,更新state,觸發(fā)UI刷新。
fish redux
部分重要概念 1. component 對局部的展示和功能的封裝。對功能細分為修改數據的功能(Reducer)和非修改數據的功能(副作用Effect)。于是有了View、Effect、Reducer組件三要素。 2. action - Action 包含兩個字段 - type - payload - 推薦的寫法是 - 為一個組件|適配器創(chuàng)建一個 action.dart 文件,包含兩個類 - 為 type 字段起一個枚舉類 - 為 Action 的創(chuàng)建起一個 ActionCreator 類,這樣利于約束 payload 的類型。 - Effect 接受處理的 Action,以 on{Verb} 命名 - Reducer 接受處理的 Action,以{verb} 命名 - 示例代碼
enum MessageAction {
onShare,
shared,
}
class MessageActionCreator {
static Action onShare(Map<String, Object> payload) {
return Action(MessageAction.onShare, payload: payload);
}
static Action shared() {
return const Action(MessageAction.shared);
}
}
- reducer
- Reducer 是一個上下文無關的 pure function。它接收下面的參數
- T state
- Action action
- 它主要包含三方面的信息
- 接收一個“意圖”, 做出數據修改。
- 如果要修改數據,需要創(chuàng)建一份新的拷貝,修改在拷貝上。
- 如果數據修改了,它會自動觸發(fā) State 的層層數據的拷貝,再以扁平化方式通知組件刷新。
- 示例代碼
Reducer<String> buildMessageReducer() {
return asReducer(<Object, Reducer<String>>{
'shared': _shared,
});
}
String _shared(String msg, Action action) {
return '$msg [shared]';
}
class MessageComponent extends Component<String> {
MessageComponent(): super(
view: buildMessageView,
effect: buildEffect(),
reducer: buildMessageReducer(),
);
}
- effect 接收View的"意圖",也包括對生命周期的回調。不修改數據,它對數據是只讀的,如果要修改,應該發(fā)送一個Action到Reducer中去處理。
cunter fish redux 版
基礎目錄 > -action.dart > -effect.dart(本例中非必須) > -page.dart > -reducer.dart > -state.dart > -view.dart
action.dart
enum CounterAction { add, onAdd }
class CounterActionCreator {
//reducer使用
static Action add() {
return const Action(CounterAction.add);
}
//effect使用
static Action onAdd() {
return const Action(CounterAction.onAdd);
}
}
state.dart
class CounterState implements Cloneable<CounterState> {
int count = 0;
@override
CounterState clone() {
return CounterState()..count = count;
}
}
CounterState initState(Map<String, dynamic> args){
//什么也沒做,只是初始化數據
return CounterState();
}
reducer.dart
Reducer<CounterState> buildReducer() {
return asReducer<CounterState>(<Object, Reducer<CounterState>>{
CounterAction.add: _add,
});
}
CounterState _add(CounterState state, Action action) {
final CounterState newState = state.clone();
newState.count = ++state.count;
return newState;
}
effect.dart
Effect<CounterState> buildEffect() {
return combineEffects(<Object, Effect<CounterState>>{
CounterAction.onAdd: _onAdd,
});
}
void _onAdd(Action action, Context<CounterState> ctx) {
print("_onAdd");
ctx.dispatch(CounterActionCreator.add());
}
view.dart
Widget buildView(
CounterState state, Dispatch dispatch, ViewService viewService) {
return Scaffold(
appBar: AppBar(
title: Text('CounterFishRedux'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
state.count.toString(),
)
],
),
),
floatingActionButton: FloatingActionButton(
//發(fā)送的action到了Effect中處理
onPressed: () => dispatch(CounterActionCreator.onAdd()),
//也可以發(fā)action到reducer中處理
//onPressed: () => dispatch(CounterActionCreator.add()),
tooltip: 'add',
child: Icon(Icons.add),
),
);
}
page.dart
class CounterFishReduxPage extends Page<CounterState, Map<String, dynamic>> {
CounterFishReduxPage()
: super(
initState: initState,
effect: buildEffect(),
reducer: buildReducer(),
view: buildView,
);
}
? 在view.dart中,用戶觸發(fā)FloatingActionButton的onPress事件,dispatch了名為onAdd的Action,在effect.dart中接收到action,會繼續(xù)dispatch,到reducer.dart中(這一步非必須,可以直接dispatch到reducer.dart中),在reducer.dart中,在state中取出state中的數據,處理(加一)后,返回state,數據更新到store中,觸發(fā)UI更新,最終到view.dart中state中的數據會更新,取出新的數據顯示。
? fish redux適用于中大型項目,這種簡單的功能直接用官方的setState即可。
? 這樣就可以單獨作為一個page或者component使用,沒有邏輯和UI的耦合。
轉自:https://zhuanlan.zhihu.com/p/62600189
資源推薦
github 上的庫包含基本小部件的代碼以及可以在該小部件中應用的大多數屬性。
https://github.com/PoojaB26/FlutterBasicWidgets
最佳教程集合
https://github.com/PoojaB26/AwesomeFlutterPlaylist
flutter 介紹
https://github.com/Solido/awesome-flutter
https://github.com/CarGuo/GSYGithubAppWeex