Flutter 状态管理,实际来说就是数据和视图的绑定和刷新;
这块对应到 H5,就比较好理解,这个概念也是从前端来到;
对应到 客户端,就是监听回调,类似事件总线(EventBus);
Provider 基本使用:
- 建议在 main 方法加上这段代码,防止热重载报错,如果还是报错就必须点击下 run 按钮了;
void main() {
WidgetsFlutterBinding.ensureInitialized();
Provider.debugCheckInvalidValueType = null;
......
}
- 创建 Model,继承 ChangeNotifier;
class ATheme with ChangeNotifier {
double textSize = 16;
int bgColor = 0xffff0000;
int textColor = 0xff666666;
void setTheme(int bgColor) {
textSize = 18;
this.bgColor = bgColor;
textColor = 0xff333333;
// 调用这个方法,通知所有监听
notifyListeners();
}
}
- 创建共享数据;
void main() {
WidgetsFlutterBinding.ensureInitialized();
Provider.debugCheckInvalidValueType = null;
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider.value(value: new ATheme()),
ChangeNotifierProvider.value(value: new LoginInfo()),
],
child: MaterialApp(
home: StartPage(),
),
),
);
}
- 绑定和刷新数据;
class ThemeChangePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 注意在 build 里面调用 Provider.of<ATheme>(context); 就会自动注册监听;也不用担心重复注册;
ATheme appTheme = Provider.of<ATheme>(context);
LoginInfo loginInfo = Provider.of<LoginInfo>(context);
return Scaffold(
// 这里可以直接使用 model 的属性了,如果有变化会自动刷新
backgroundColor: Color(appTheme.bgColor),
appBar: AppBar(
title: Text("改变主题 ${loginInfo.name}"),
),
body: Column(
children: <Widget>[
FlatButton(
onPressed: () {
appTheme.setTheme(0xffff00ff);
},
child: Text("红"),
),
FlatButton(
onPressed: () {
appTheme.setTheme(0xff00ffff);
},
child: Text("黄"),
),
FlatButton(
onPressed: () {
appTheme.setTheme(0xff0000ff);
},
child: Text("蓝"),
),
],
),
);
}
}
如果我只是想要监听回调,比如登陆后跳转到某个页面;
class LoginInfoManager with ChangeNotifier {
static LoginInfoManager instance = LoginInfoManager();
String id = "没信息ID";
String name = "没信息name";
void setLoginInfo() {
id = "测试ID";
name = "测试名称";
notifyListeners();
}
}
class _StartPageState extends State<StartPage> {
@override
void initState() {
super.initState();
// 手动添加监听
LoginInfoManager.instance.addListener(onLoginChanged);
}
void onLoginChanged() {
LoginInfoManager loginInfo = LoginInfoManager.instance;
print("${loginInfo.name}");
}
@override
void dispose() {
// 手动移除监听
LoginInfoManager.instance.removeListener(onLoginChanged);
super.dispose();
}
}
总结
- 本身使用是很简单的;
- 简化了监听回调,实际是内部自动注册监听了;
- 注意局部使用 Provider;并不是所有数据都要放在 main 里面,放到使用到数据的顶层就行了;