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])},
);
 
 |