杠精求放过
redux是全局状态管理插件,但是它也可以解决build在setState以后调用问题;
- 这里有一个疑问,Redux是最顶层传入的,那么层层遍历找到这个值是否也很耗费性能;
setState和redux
setState每次使用都会重新渲染整个页面
//在一个使用flutter create .创建的模板项目中
//我们在_MyHomePageState的Widget build里面加一个print
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
//你会发现当你每次点击悬浮按钮的时候都会打印'build runing ?'
print('build runing ?');
return Scaffold(...
);
}
}
void _increment() {
setState(){
//这个玩意每次执行完成以后
//flutter都要去重新执行build
//数据量小一点也还ok
//如果数据量很大,那无疑这个就是噩梦了
_counter ++
}
}
刚开始我还不知道咋解决这个问题,我想先试试redux
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
flutter_redux: ^0.7.0
然后
// 定义store
class AppStore {
int count = 0;
AppStore.initCount() {
this.count = 0;
}
AppStore(this.count);
}
// 定义actions
enum AppActions { Increment }
// 定义reducer
AppStore reducer(AppStore store, dynamic actions) {
print('store runing reducer');
switch (actions['type']) {
case AppActions.Increment:
//定义count++也就是_increment
store.count++;
return store;
default:
return store;
}
}
顶层入口传入Store
void main() {
// 初始化 store
final Store store =
Store<AppStore>(reducer, initialState: AppStore.initCount());
// store作为参数要放到application的最顶层
runApp(MyApp(store: store));
}
StoreProvider包裹MaterialApp
class MyApp extends StatelessWidget {
final Store<AppStore> store;
const MyApp({Key key, this.store}) : super(key: key);
@override
Widget build(BuildContext context) {
// 整个application的最顶层是StoreProvider
return StoreProvider(
store: store,
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
));
}
}
修改floatingActionButton Widget
// 使用store里面的reducer
floatingActionButton: StoreConnector<AppStore, Function>(
// 这里箭头函数要注意
// dispatch 调用reducer
// 参数就是action ,上面定义了action的类型是dynamic
// 所以这里理论上是可以传入任意的值
// 但是我习惯用map类型
// 这里map里可以定义两个key
// 一个是type,也就是action
// 一个是data,也就是要传入的数据
// 在flutter_redux中converter的返回值作为builder的第二个参数
// 而这个参数可以是state也可以是reducer
converter: (store) => () => store.dispatch({
"type": AppActions.Increment, /*"data":""*/
}),
builder: (context, callback) {
return FloatingActionButton(
onPressed: callback,
tooltip: 'Increment',
child: Icon(Icons.add),
);
}),
修改Text Widget:
// 使用store.state.count
// 注意这里的类型<AppStore, String>
StoreConnector<AppStore, String>(converter: (store) {
return store.state.count.toString();
},
builder: (context, count) {
return Text(
'$count',
style: Theme.of(context).textTheme.headline4,
);
}),
store里面的print('store runing reducer');
然后你就会发现build这玩意不再打印