在使用Provider的时候,我们主要关心三个概念:
前提条件:
使用之前,我们需要先引入对它的依赖,截止这篇文章,Provider的最新版本为6.0.4:
dependencies:
provider:^4.0.4
第一步:创建自己的ChangeNotifier
(这里可以对每个需要共享的数据创建自己的文件进行管理)
/**
* 使用继承自ChangeNotifier,也可以使用混入,这里取决于是否需要已经继承了其他的类
* 创建一个私有的 _counter,并且提供get set方法
* 在set方法中监听 _counter的改变,如果改变就调用 notifyListeners方法、通知所有的Consumer进行更新
*/
class CounterProvider extends ChangeNotifier {
int _counter = 100;
int get counter => _counter;
set counter(int value) {
_counter = value;
notifyListeners(); // 通知所有的Consumer进行更新
}
}
import'package:flutter/material.dart';
class UserInfo {
String nickname;
int level;
UserInfo(this.nickname, this.level);
}
class UserProvider extends ChangeNotifier {
UserInfo _userInfo = UserInfo("why", 18);
set userInfo(UserInfo info){
_userInfo = info;
notifyListeners();
}
get userinfo{
return _userInfo;
}
}
第二步:在Widget Tree中插入ChangeNotifierProvider
void main() {
runApp(
// ChangeNotifierProvider 放到顶层,这样方便在整个应用的任何地方可以使用 CounterProvider
MultiProvider(providers: [
// 存放多个共享数据
ChangeNotifierProvider(create: (ctx)=> CounterProvider()),
ChangeNotifierProvider(create: (ctx) => UserProvider())
],
child: MyApp(),
),
);
}
第三步:在首页中使用Consumer引入和修改状态
(这里使用了Selector 替换了Consumer进行了优化 )
class _MyHomePageState extends State<MyHomePage> {
void initState() {
super.initState();
}
Widget build(BuildContext context) {
return Scaffold(
// 脚手架
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column (
mainAxisAlignment: MainAxisAlignment.center,
children: [
HYShowData01(),
HYShowData02(),
],
),
),
floatingActionButton: Selector<CounterProvider,CounterProvider> (
// 某种情况下使用 Selector代替Consumer,性能会更高
selector: (ctx,provider) => provider,
shouldRebuild: (pre, next) => false,// 是否需要重新 build
builder: (ctx, counterPro,child) {
print("floatingActionButton 展示位置builder被调用");
return FloatingActionButton(
child: child,
onPressed: () {
counterPro.counter +=1;
});
},
child: const Icon(Icons.add),
),
);
}
}
class HYShowData01 extends StatelessWidget {
Widget build(BuildContext context) {
print("HYShowData01");
return Consumer<CounterProvider>(
builder: (ctx, counterPro, child) {
// ctx: 每个build 方法都会有上下文,目的是知道当前树的位置
// counterPro:对应的实例,也是我们在builder函数中主要使用的对象
// child: 目的是进行优化,如果builder下面有一颗庞大的子树,当模型发生改变的时候,我们并不希望重新build这颗子树,那么就可以将这颗子树放到Consumer的child中,在这里直接引用即可
print("HYShowData011");
return Text("共享状态:${counterPro.counter}");
},
);
}
}
class HYShowData02 extends StatefulWidget {
State<HYShowData02> createState() => _HYShowData02State();
}
class _HYShowData02State extends State<HYShowData02> {
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
}
Widget build(BuildContext context) {
// 使用Consumer 是为了尽可能少的 rebuild widget
// 当我们点击了 FloatingActionButton时,HomePage的build方法会被重新调用,这意味着HomePage的widget的widget都需要重新build
// 使用Consumer 会发现 Homepage的build方法不会被重新调用
print("_HYShowData02State");
return Consumer<CounterProvider>(builder: (ctx, counterPro,child) {
print("_HYShowData022State");
return Text("共享状态:${counterPro.counter}");
});
}
}