好久没更新了,=-= ·因为搞前端去了·抽空还是把自己学习的捋一下,状态管理简单的一些使用
InheritedWidget
可以实现跨组件数据的传递
- 定义
class HJCounterWidget extends InheritedWidget{
/// 需要共享的状态
final int counter;
///定义构造方法
HJCounterWidget({this.counter, Widget child}): super(child:child);
///获取组件最近的当前InheritedWidget
static HJCounterWidget of(BuildContext context){
///沿着Element树, 去找到最近的HYCounterElement, 从Element中取出Widget对象
return context.dependOnInheritedWidgetOfExactType();
}
/// 必须实现的方法
/// 如果返回true: 执行依赖当期的InheritedWidget的State中的didChangeDependencies
/// 绝对要不要回调State中的didChangeDependencies
@override
bool updateShouldNotify(HJCounterWidget oldWidget) {
// TODO: implement updateShouldNotify
return oldWidget.counter != counter;
}
}
- 使用
class _HJStateTestPageState extends State{
int _count = 100;
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('状态管理'),
),
body: HJCounterWidget(
counter: _count,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [HJShowData1(), HJShowData2()],
),
)),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.data_usage),
onPressed: (){
setState(() {
_count++;
});
},
),
);
}
}
class HJShowData1 extends StatefulWidget{
@override
State createState() {
// TODO: implement createState
return _HJShowData1State();
}
}
class _HJShowData1State extends State{
/// build 出来的widget 依赖的HJCounterWidget的数据发生改变时调用
@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
HJLog('_HJShowData1State didChangeDependencies', StackTrace.current);
}
@override
Widget build(BuildContext context) {
int counter = HJCounterWidget.of(context).counter;
return Card(
color: Colors.blue,
child: Text('当前计数:$counter',style: TextStyle(fontSize: 20),),
);
}
}
class HJShowData2 extends StatelessWidget{
@override
Widget build(BuildContext context) {
int counter = HJCounterWidget.of(context).counter;
// TODO: implement build
return Container(
child: Text('当前计数:$counter',style: TextStyle(fontSize: 20)),
color: Colors.amberAccent,
);
}
}
Provider
Provider
是官方推荐的全局状态管理工具
主要看以下几个概念
- ChangeNotifier:存数据的地方
- ChangeNotifierProvider:提供数据的地方
- Consumer:使用数据的地方
步骤
/**
* 1.创建自己需要共享的数据
* 2.在应用程序的顶层ChangeNotifierProvider
* 3.在其它位置使用共享的数据
* > Provider.of: 当Provider中的数据发生改变时, Provider.of所在的Widget整个build方法都会重新构建
* > Consumer(相对推荐): 当Provider中的数据发生改变时, 执行重新执行Consumer的builder
* > Selector: 1.selector方法(作用,对原有的数据进行转换) 2.shouldRebuild(作用,要不要重新构建)
*/
举个栗子
- 创建自己需要共享的数据
/// 1.创建自己需要共享的数据
/// 快捷键,选中类,cmd+n 自动生成get,set方法
class HJCounterViewModel extends ChangeNotifier {
int _counter = 100;
int get counter => _counter;
set counter(int value) {
_counter = value;
notifyListeners();
}
}
- 在应用程序的顶层ChangeNotifierProvider
void main() {
runApp(
ChangeNotifierProvider(create: (ctx) {
return HJCounterViewModel();
},child: MyApp(),));
}
- 在其它位置使用共享的数据,3种
1. int counter = Provider.of(context).counter;
2. Selector(
selector: (ctx, counterVM)=>counterVM,
shouldRebuild: (pre, next)=>false,/// 是否重新build
builder: (ctx, counterVM, child){
HJLog('builder ', StackTrace.current);
return FloatingActionButton(
child: Icon(Icons.data_usage),
onPressed: (){
counterVM.counter += 1;
},
);
},
),
3. Consumer(
builder: (ctx, counterVM, child){
return FloatingActionButton(
child: Icon(Icons.data_usage),
onPressed: (){
counterVM.counter += 1;
},
);
},
),
多个Provider
class HJUserViewModel extends ChangeNotifier {
UserInfo _user;
HJUserViewModel(this._user);
UserInfo get user => _user;
set user(UserInfo value) {
_user = value;
notifyListeners();
}
}
class UserInfo {
String name;
int age;
double height;
UserInfo(this.name, this.age, this.height);
}
List providers = [
ChangeNotifierProvider(create: (ctx) => HJUserViewModel(UserInfo('hj',18,180))),
ChangeNotifierProvider(create: (ctx) => HJCounterViewModel())
];
void main() {
/// 多个provider
runApp(
MultiProvider(
providers: providers,
child: MyApp(),
)
);
}
- 使用同单个Provider,可以多个provider使用
Consumer2(builder: (ctx, userVM, counterVM, child){
return Text(
'当前计数:${counterVM.counter} - name:${userVM.user.name} age:${userVM.user.age} height:${userVM.user.height}',
style: TextStyle(fontSize: 20, color: Colors.deepOrangeAccent),
maxLines: 5,
);
})
- 可能还有一些依赖关系,实际项目可以捋一捋
List providers = [
// ChangeNotifierProvider(create: (ctx) => HJMealViewModel()),
ChangeNotifierProvider(create: (ctx) => HJFilterViewModel()),
ChangeNotifierProxyProvider(
create: (ctx) =>HJMealViewModel(),
update: (ctx,filterVM,mealVM){
mealVM!.updateFilters(filterVM);
return mealVM;
}),
ChangeNotifierProxyProvider2(
create: (ctx) =>HJCollectViewModel(),
update: (ctx,filterVM,mealsVM,collectVM){
collectVM!.updateFilters(filterVM);
collectVM.updateMeals(mealsVM);
return collectVM;
}
)
];