当我们想在多个界面(组件、Widget)共享状态(数据)。可以使用官方推荐的 ‘provider’
InheritedWidget
原生flutter中, InheritedWidget 可以进行状态管理。
class CounterWidget extends InheritedWidget {
final int count;
const CounterWidget({super.key, required super.child, required this.count});
/// 重写此方法
@override
bool updateShouldNotify(covariant CounterWidget oldWidget) {
// TODO: implement updateShouldNotify
return oldWidget.count != count;
}
/// 返回对象
static CounterWidget? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType();
}
}
在子组件获取状态
用法比较麻烦 还是使用官方推荐的 provider
provider
引入到yaml中 ,并 pub get
provider: ^6.0.5
举个例子,app内用户信息想要共享。
用户模型层,继承 ChangeNotifier
class UserData extends ChangeNotifier {
String name = '';
int _age = 0;
int get age {
return _age;
}
set age(int age) {
_age = age;
notifyListeners();
}
}
class UserData with ChangeNotifier {
String name = '';
int _age = 0;
int get age {
return _age;
}
set age(int age) {
_age = age;
notifyListeners();
}
}
extends 和 with 好像都可以 以后再来解释这个吧。
在设置age的时候 触发。
顶部的Widget配置
单个数据
runApp(
ChangeNotifierProvider(create: (BuildContext context) {
return UserData();
}, child: const MyApp(),),
);
多个数据共享
runApp(MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) {
return UserData();
},
),
ChangeNotifierProvider(create: (context) {
return AppConfig();
},),
],
child: const MyApp(),
));
项目中使用
获取状态(数据)
- of
- Consumer
触发
根据用户模型层可以发现 只要改变age 或者 config中的value值 即可
UserData share = Provider.of(context);
AppConfig config = Provider.of(context);
onPressed: () {
// 不需要 setState((){})
share.age++;
config.setValue(share.age * share.age);
},
此处省略了 setState((){})
使用细节
点击事件中使用
UserModel userModel = Provider.of(context);
print(userModel.isLogin);
报错
======== Exception caught by gesture ===============================================================
The following assertion was thrown while handling a gesture:
Tried to listen to a value exposed with provider, from outside of the widget tree.
This is likely caused by an event handler (like a button's onPressed) that called
Provider.of without passing `listen: false`.
To fix, write:
Provider.of<UserModel>(context, listen: false);
It is unsupported because may pointlessly rebuild the widget associated to the
event handler, when the widget tree doesn't care about the value.
The context used was: SliverGrid(delegate: SliverChildBuilderDelegate#2f654(estimated child count: 5), renderObject: RenderSliverGrid#46fac relayoutBoundary=up2)
'package:provider/src/provider.dart':
Failed assertion: line 274 pos 7: 'context.owner!.debugBuilding ||
listen == false ||
debugIsInInheritedProviderUpdate'
修改成
UserModel userModel = Provider.of(context, listen: false);