对于之前开发react的同学来说,redux应该一点都不陌生。
管理不断变化的 state 非常困难。如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依次地,可能会引起另一个 view 的变化。直至你搞不清楚到底发生了什么。state 在什么时候,由于什么原因,如何变化已然不受控制。当系统变得错综复杂的时候,想重现问题或者添加新功能就会变得举步维艰。
同时,有时候在处理兄弟组件数据的传递上,没有一个状态管理的库也会显得有些繁琐。
为此,redux能很好地解决这些问题。那么如何在flutter中引入redux及相关debug库呢。首先,在pubspec.yaml文件中,加入这几个库的依赖,保存后,flutter会自动安装。
相应的库安装完毕,接下来就是要将对应的包引入文件中:
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
import 'package:redux_dev_tools/redux_dev_tools.dart';
import 'package:redux_remote_devtools/redux_remote_devtools.dart';
这里我们会以经典的计数器为例,首先是action和reducer的创建
enum Actions { Increment }
class AppState {
final int count;
AppState(this.count);
factory AppState.initial() => AppState(1);
}
AppState counterReducer(AppState state, dynamic action) {
if (action == Actions.Increment) {
return new AppState(state.count + 1);
} else {
return state;
}
}
在main函数中,创建reducer实例,同时将RemoteDevToolsMiddleware同步调试中间件引入,注意,这里remoteDevtools.connect()的链接是一个异步方法。
var remoteDevtools = RemoteDevToolsMiddleware('10.242.120.233:8000');
final Store<AppState> store = new DevToolsStore(
counterReducer,
/* Function defined in the reducers file */
initialState: AppState.initial(),
middleware: [
remoteDevtools,
],
);
remoteDevtools.store = store;
await remoteDevtools.connect();
runApp(new FlutterReduxApp(
title: 'Flutter Redux Demo',
store: store,
));
}
在StoreConnector 将state拿出转化为需要显示的计数。
new StoreConnector<AppState, String>(
converter: (store) => store.state.count.toString(),
builder: (context, count) {
return new Text(
count,
style: Theme.of(context).textTheme.display1,
);
},
)
在然后在按钮的StoreConnector中dispatch对应的action:
floatingActionButton: new StoreConnector<AppState, VoidCallback>(
converter: (store) {
// Return a `VoidCallback`, which is a fancy name for a function
// with no parameters. It only dispatches an Increment action.
return () => store.dispatch(Actions.Increment);
},
builder: (context, callback) {
return new FloatingActionButton(
// Attach the `callback` to the `onPressed` attribute
onPressed: callback,
tooltip: 'Increment',
child: new Icon(Icons.add),
);
},
)
为了能够更直观的在展示action的展示state和action变化,需要你本地安装remotedev-server。
npm install -g remotedev-server
remotedev --port 8000
https://www.zhihu.com/video/1073643446832730112
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!