Provider状态管理
安装Provider
Provider全局注册
- 如果需要在跨路由页面中共享数据,则需要放在MaterialApp上方包裹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => LikeModel(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routes: {
"/": (context) => const MyHomePage(title: 'Flutter Demo Home Page'),
"/detail" : (context) => const DetailPage(),
},
),
);
}
}
|
模型类
需要监听值的变化动态刷新页面的类需要继承ChangeNotifier
不需监听值的变化的则直接使用class即可
使用extends 和 with都可以
| class Test extends ChangeNotifier{
}
|
| class Test with ChangeNotifier{
}
|
模型类示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | class LikeModel extends ChangeNotifier {
final List<int> _likes = [];
UnmodifiableListView<int> get items => UnmodifiableListView(_likes);
bool hasSelected(int value) {
return _likes.contains(value);
}
void add(int selected) {
_likes.add(selected);
// 在修改后需要通知的方法结尾调用以下代码
// 用于通知依赖此模型的Widget更新页面
notifyListeners();
}
void remove(int selected) {
_likes.remove(selected);
notifyListeners();
}
}
|
Provider分类
获取数据的方法
- context.read
只在页面刷新时读取数据,不监听数据的变化
不可以用于build方法内
可以用于回调函数内
| ElevatedButton(
onPressed: () => {context.read<ThemeChanger>().change()},
child: const Text("change theme"),
),
|
- context.watch
会根据数据的变化而更新页面的值
| Text(context.watch<TestModel>().toString()),
|
- context.select
获取指定单个值
可监听数据更新
也可用于不可变数据
| var name = context.select<TestModel, String>((value) => value.name);
|
- 行为和context.watch相同
会监听值的变化
| Text(Provider.of<TestModel>(context).name),
|
- 行为和context.read相同
但是可用于build方 法
不会监听值的变化
| Provider.of<T>(context,listen=false)
|
| Provider.of<ThemeChanger>(context,listen=false).change()
|
- 订阅值的另一种写法
| Consumer<T>(builder:(context,T value,child)=>Widget)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | return ListTile(
title: Text("List Item ${list[i]}"),
trailing: Consumer<LikeModel>(
builder: (context, value, child) {
bool selected = value.hasSelected(list[i]);
return IconButton(
icon: Icon(selected ? Icons.favorite : Icons.favorite_border),
color: selected ? Colors.red : null,
onPressed: () {
_toggleBtn(value, list[i]);
},
);
},
),
onTap: () => {log("${list[i]}"), _navigator(context, list[i])},
);
|