他其实是状态管理:App内有多个地方使用到登陆用户的数据,这时候如果某处对用户数据做了修改,各个页面的同步更新会是一件麻烦的事情。但是引入 Redux 后,某个页面修改了当前用户信息,所有绑定了 Redux 的控件,将由 Redux 自动同步刷新。
第一步我们需要创建一个State类,这里保存着需要全局的对象。状态是由reducer生成并储存在Store里面的。Store更新状态的时候,并不是更改原来的状态对象,而是直接将reducer生成的新的状态对象替换掉老的状态对象。
class UserInfoState {
UserInfo userInfo;
UserInfoState(this.userInfo);
}
第二步创建action。这个action其实就是对状态进行操作的方法的一个代号
class UpdateUserInfoAction {
final UserInfo userInfo;
UpdateUserInfoAction(this.userInfo);
}
第三步创建reducer。这个reducer这里一共有两个,一个是创建Store时需要的,一个则是生成新的状态的reducer
UserInfoState appReducer(UserInfoState userInfoState, action) {
return UserInfoState(UserInfoReducer(userInfoState.userInfo, action));
}
final UserInfoReducer = combineReducers<UserInfo>([
TypedReducer<UserInfo, UpdateUserInfoAction>(_updateUser),
]);
UserInfo _updateUser(UserInfo info, UpdateUserInfoAction action) {
info = action.userInfo;
return info;
}
userInfo如下
class UserInfo {
String name;
int id;
UserInfo(this.name, this.id);
UserInfo.empty();
}
到此准备工作已经做好了。
第四步要在APP的顶层创建这个store(runApp前或者MyApp(store))
void main() {
final store = Store<UserInfoState>(appReducer,
initialState: new UserInfoState(UserInfo.empty()));
runApp(MyApp(store));
}
而且在MyApp中build时,其根节点为StoreProvider
class MyApp extends StatelessWidget {
final Store<UserInfoState> store;
MyApp(this.store);
@override
Widget build(BuildContext context) {
return StoreProvider(
store: store,
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: TopScreen(),
),
);
}
}
第五步则是在子页面中使用或者更新这个State,我们通常使用StoreConnector,因为只要State更新,他就会rebuild,比如这里的top_screen 首先看看需要刷新的使用
class TopScreen extends StatefulWidget {
@override
_TopScreenState createState() => _TopScreenState();
}
class _TopScreenState extends State<TopScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Top Screen'),
),
body: Center(
child: StoreConnector<UserInfoState,UserInfo>(
converter: (store) => store.state.userInfo,
builder: (context, userInfo) {
return Text(
userInfo.id.toString(),
style: Theme.of(context).textTheme.display1,
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context){
return MyHomePage();
}));
},
child: Icon(Icons.forward),
),
);
}
}
可以看到我们在构建的时候,将Widget的生成放到StoreConnector的builder中,如果在其他页面更改了UserInfo,那么这里会实时的更改。至于发送更新的action,我们也可以按照上面的方式,也可以直接用 store.dispatch(action);store的获取store = StoreProvider.of(context);该段代码应该放在stateClass中获取,比如这里是在 didChangeDependencies()方法中获取的。然后在build中直接发送action。如果还是放在StoreConnector中则如下
floatingActionButton: StoreConnector<CountState,VoidCallback>(
converter: (store) {
return () => store.dispatch(Action.increment);
},
builder: (context, callback) {
return FloatingActionButton(
onPressed: callback,
child: Icon(Icons.add),
);
},
),