Redux 主要由3部分组成,Store、Action、Reducer。
Store位于整个APP的顶层,存储和管理state;
Action简单点就是动作,通过发起一个Action来告诉Reducer该更新状态了;
Reducer根据Action产生新的状态;
第一步:导包:
flutter_redux: ^0.5.3
第二步:创建State
ReduxState.dart
//定义一个state
class ReduxState {
String name;
ReduxState.initState() : name = "666";
}
第三步:创建action
ReduxState.dart
//定义action
enum Action {
Change
}
第四步:创建reducer
ReduxState.dart
//定义reducer
ReduxState getReduce(ReduxState state, action) {
if(action == Action.Change) {
String nname = "1";
state.name = state.name + nname;
}
return state;
}
第五步:创建全局Store
main.dart
main() {
final store = Store<ReduxState>(
getReduce,
initialState: ReduxState.initState()
);
runApp(ReduxDemo3(store,));
}
第六步:将Store跟根Widget关联
main.dart
注意:
1、最顶层必须是 StoreProvider 开始
2、StoreBuilder后要跟上我们定义的那个State类,要不会报错,
class ReduxDemo3 extends StatelessWidget {
final Store<ReduxState> store;
ReduxDemo3(this.store);
@override
Widget build(BuildContext context) {
return StoreProvider(
store: store,
child: StoreBuilder<ReduxState>(builder: (BuildContext context, Store<ReduxState> store){
return MaterialApp(
title: 'ReduxDemo3',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: FirstPage(),
);
})
);
}
}
第七步:一级子界面的构建由StoreBuilder开始
first_page.dart
注意:builder方法里有2个值,context和store,我们自定义的State类可以从store中获取
@override
Widget build(BuildContext context) {
return StoreBuilder<ReduxState>(
builder: (BuildContext context, Store<ReduxState> store){
return Scaffold(
appBar: AppBar(
title: Text("ReduxDemo3"),
),
body: Center(
child: Column(
children: <Widget>[
Text(store.state.name),
SizedBox(height: 100,),
FlatButton(
onPressed: (){
Navigator.of(context).push(MaterialPageRoute(builder: (context){
return NextPage();
}));
},
child: Text("下一页")
)
],
)
),
);
}
);
}
第八步:二级子界面的构建由StoreBuilder开始
next_page.dart
注意:State数据的修改是由Store来发起Action,通知Reducer修改数据,方法为store.dispatch(定义的action)
@override
Widget build(BuildContext context) {
return StoreBuilder<ReduxState>(
builder: (BuildContext context, Store<ReduxState> store){
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
Text(store.state.name),
SizedBox(height: 100,),
FlatButton(
onPressed: (){
store.dispatch(Action.Change);
},
child: Text("点击变换数据")
)
],
)
),
);
}
);
}
第九步:效果图
第十步:对比StoreBuilder和StoreConnector
该例子里的界面构建使用的是StoreBuilder来构建,也可以使用StoreConnector来构建,两者就差一个参数。
StoreConnector主要是有个数据转化的作用,可以对数据先做一些转化操作再赋值到组件上
class StoreConnector<S, ViewModel> extends StatelessWidget
StoreBuilder是直接将数据给显示在组件上
class StoreBuilder<S> extends StatelessWidget
修改第二个界面里的body的代码,将显示的Text换成用StoreConnector来包装
body: Center(
child: Column(
children: <Widget>[
StoreConnector<ReduxState, String>(
converter: (store) => store.state.name,
builder: (BuildContext context, String name) {
return Text(name);
},
),
SizedBox(height: 100,),
StoreBuilder<ReduxState>(
builder: (context, store) {
return FlatButton(
onPressed: (){
store.dispatch(Action.Change);
},
child: Text("点击变换数据")
);
}
),
],
)
),
代码分析:
StoreConnector 需要两个泛型
1、一个是我们创建的 State(ReduxState)
2、一个是 ViewModel
StoreConnector 要定义两个函数
1、一个是 converter,转化函数,从 Store 中拿出修改的数据 store.state.name
2、一个是 builder,将 converter 返回的 name 进一步转化为界面:Text(name)。
ViewModel决定了converter(转换函数)那边的返回值类型,这边我们将它定义为String,因为转换函数里返回的是ReduxState里的name字段。
builder 这边有2个值,上下文和转换函数返回的值。因为转换函数返回的是String类型的字段,所有我们这样表示,(BuildContext context, String name) { return Text(name) }。
假如转换函数返回的是个ReduxState对象,那就得这样表示
(BuildContext context, ReduxState state) { return Text(state.name) } 。