状态管理-Provider
2021-11-24 本文已影响0人
Jean_Lina
provider:官方推荐的全局状态管理工具
使用之前,先在pubspec.yaml引入对它的依赖 provider: ^6.0.0
使用步骤:
(1)创建ChangeNotifier,真正数据(状态)存放的地方
class DBJHomeViewModel extends ChangeNotifier {
int _counter = 890;
int get counter => _counter;
set counter(int value) {
_counter = value;
// 通知所有的依赖者进行更新
notifyListeners();
}
DBJHomeViewModel(this._counter);
}
(2)在Widget Tree中插入ChangeNotifierProvider,Widget树中提供数据(状态)的地方,会在其中创建对应的ChangeNotifier。将ChangeNotifierProvider放到了顶层,这样方便在整个应用的任何地方可以使用共享数据
main() {
runApp(
ChangeNotifierProvider(
child: DBJMyApp(),
create: (cxt) => DBJHomeViewModel(209), //共享数据
),
);
}
(3)使用共享数据
获取共享数据方法:
😊 Provider.of<T>(context);
😁 Consumer<T>
😊 Selector<A, S>
Widget build(BuildContext context) {
print('_DBJContentWidgetState 执行build');
return Scaffold(
appBar: AppBar(
title: Text('状态管理-Consumer'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
DBJGoodsInfo(), //Provider 依赖数据展示
SizedBox(height: 30),
DBJShopCarInfo(), //Consumer 依赖数据展示
],
),
),
floatingActionButton: buildFloatButtonWithConsumer(),
);
}
🍊 使用Consumer构建悬浮button:
// 使用Consumer对共享数据进行修改
Widget buildFloatButtonWithConsumer() {
return Consumer<DBJHomeViewModel>(
builder: (cxt, viewModel, child) {
print('floatingActionButton Consumer 执行build');
return FloatingActionButton(
onPressed: () {
print('点击++');
//修改counter共享数据
viewModel.counter++;
},
//直接引入Consumer的child,不进行新的构建
child: child,
);
},
child: Icon(Icons.inbox_rounded),
);
}
🍊 使用Selector构建悬浮button:
优化后:不依赖共享数据展示,只对共享数据进行修改
1:Provider.of<DBJHomeViewModel>(context, listen: false);
Widget buildFloatButtonWithProvider() {
print('floatingActionButton 执行build');
return FloatingActionButton(
onPressed: () {
print('点击++');
DBJHomeViewModel viewModel =
Provider.of<DBJHomeViewModel>(context, listen: false);
viewModel.counter++; //修改counter共享数据
},
child: Icon(Icons.inbox_rounded),
);
}
2:使用Selector的shouldRebuild避免重复build
Widget buildFloatButtonWithSelector() {
return Selector<DBJHomeViewModel, DBJHomeViewModel>(
selector: (cxc, viewModel) {
return viewModel;
},
shouldRebuild: (previous, next) => false, // 不重新build
child: Icon(Icons.inbox_rounded),
builder: (BuildContext context, viewModel1, Widget? child) {
print('floatingActionButton Selector 执行build');
return FloatingActionButton(
onPressed: () {
print('点击++');
viewModel1.counter++; //修改counter共享数据
},
child: child,
);
},
);
}
🍎 优化前(使用Provider获取数据,每次数据变化build方法重新执行)
class _DBJGoodsInfoState extends State<DBJGoodsInfo> {
Widget buildWidgetWithProvider() {
print('商品信息 执行build');
int number = Provider.of<DBJHomeViewModel>(context).counter;
return Card(
child: Text(
'商品信息:$number',
style: TextStyle(fontSize: 18, color: Colors.purple),
),
);
}
🍎 优化后(使用Consumer获取数据减少build,每次数据变化仅Consumer内部的build方法重新执行)
Widget buildWidgetWithConsumer() {
print('商品信息 执行build');
return Card(
child: Consumer<DBJHomeViewModel>(
builder: (BuildContext context, viewModel, Widget? child) {
print('商品信息 Consumer 执行build');
return Text(
'商品信息:${viewModel.counter}',
style: TextStyle(fontSize: 18, color: Colors.purple),
);
},
),
);
}
@override
Widget build(BuildContext context) {
return buildWidgetWithProvider();
return buildWidgetWithConsumer();
}
}
🍎 最优方案(使用Selector,当viewModel中的其他数据发生变化,不依赖某个共享数据的其他widge,该build方法不会重新执行)
Widget buildPriceWidget() {
print('价格信息 buildPriceWidget');
return Selector<DBJHomeViewModel, DBJHomeViewModel>(
selector: (cxt, vm) {
return vm;
},
builder: (cxt, vm, child) {
print('价格信息 Selector 执行build');
return Container(
child: Text(
'价格信息:${vm.price}',
style: TextStyle(fontSize: 18, color: Colors.green),
),
);
},
);
}





