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 裏面,放到使用到數據的頂層就行了;