Flutter中的状态管理
InheritedWidget
- 找到需要共用属性/模型的多个Widget的共有父Widget
- 用自定义的InheritedWidget包裹该父类
- 在子Widget内部通过context获取共有属性/模型,进行显示
- 修改值的话,在共有父Widget的build方法内部修改变量值,重新赋值给自定义InheritedWidget即可
- 通常用来共享数据
Demo示例(OSNavigator无需关心)
import 'package:flutter/material.dart';
import 'package:flutter_navigator/Core/OSState.dart';
import 'package:flutter_navigator/OSNavigator/OSNavigator.dart';
import 'Model/VideoModel.dart';
// 状态管理类
class AMCommonStateWidget extends InheritedWidget {
final int count;
AMCommonStateWidget({required this.count, required Widget child})
: super(child: child);
static AMCommonStateWidget? of(BuildContext context) {
// 沿着Element树,去找最近的AMCommonStateElement, 从Element中取出Widget对象
return context.dependOnInheritedWidgetOfExactType();
}
@override
bool updateShouldNotify(covariant AMCommonStateWidget oldWidget) {
// TODO: implement updateShouldNotify
return oldWidget.count != count;
}
}
class AMHomePage extends StatefulWidget {
const AMHomePage({Key? key}) : super(key: key);
@override
_AMHomePageState createState() => _AMHomePageState();
}
class _AMHomePageState extends OSState<AMHomePage> {
var listener;
@override
void initState() {
// TODO: implement initState
super.initState();
OSNavigator.getInstance().addListener(this.listener = (current, pre) {
print("当前页面:${current.page}");
print("上一个页面:${pre.page}");
});
}
@override
void dispose() {
// TODO: implement dispose
OSNavigator.getInstance().removeListener(this.listener);
super.dispose();
}
// 变量声明在 build方法外面,如果在build内部声明,重新build每次都会声明,相当于变量永远是新的,值永远是初始化的值
var count = 15;
Widget build(BuildContext context) {
// 默认初始化10
return Scaffold(
appBar: AppBar(
title: Text("逻辑资源"),
),
body: AMCommonStateWidget(
count: count,
child: Column(
children: [
Container(
height: 110,
width: double.infinity,
child: Card(
color: Colors.orange,
child: Column(
children: [
MaterialButton(
color: Colors.redAccent,
textColor: Colors.white,
onPressed: () {
OSNavigator.getInstance().onJumpTo(
RouteStatus.homeDetail,
args: {"videoModel": VideoModel(180)});
},
child: Text("点击跳转详情"),
),
MaterialButton(
color: Colors.redAccent,
textColor: Colors.white,
onPressed: () {
// 修改变量
setState(() {
count++;
});
},
child: Text("计数器+1"),
),
],
),
),
),
AMCardView01(),
AMCardView02()
],
),
),
);
}
}
class AMCardView01 extends StatelessWidget {
const AMCardView01({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
var resCount = AMCommonStateWidget.of(context)?.count;
resCount ??= 10;
return Container(
height: 80,
width: double.infinity,
child: Card(
color: Colors.orange,
child: Column(
children: [
Center(
child: Text("当前的数量为$resCount"),
)
],
),
),
);
}
}
class AMCardView02 extends StatelessWidget {
const AMCardView02({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
var resCount = AMCommonStateWidget.of(context)?.count;
resCount ??= 10;
return Container(
height: 80,
width: double.infinity,
child: Card(
color: Colors.yellow,
child: Column(
children: [
Center(
child: Text("当前的数量为$resCount"),
)
],
),
),
);
}
}
Provider
- 官方推荐的状态管理工具,相当重要
- ChangeNotifier:真正数据(状态)存放的地方
- ChangeNotifierProvider:Widget树中提供数据(状态)的地方,会在其中创建对应的ChangeNotifier
- Consumer:Widget树中需要使用数据(状态)的地方
- Provider.of:当Provider中数据发生改变时,Provider.of所在的Widget整个build方法都会重新构建
- Consumer(相对推荐):当Provider中的数据改变时,Consumer的builder方法会重新构建
- Selector: 1.selector方法(作用对原有数据进行转换)2.shouldRebuild(作用是否需要重新构建)
四步骤上手Provider
- 创建自己需要共享的数据
- 在程序的顶层创建ChangeNotifierProvider
- 在其他位置共享数据
- Consumer 修改数据通知更新(局部更新)
import 'package:flutter/material.dart';
import 'package:flutter_navigator/Core/OSState.dart';
import 'package:flutter_navigator/OSNavigator/OSNavigator.dart';
import 'package:provider/provider.dart';
import 'Model/VideoModel.dart';
/// 四步骤上手Provider
/// 1.创建自己需要共享的数据
/// 2.在程序的顶层创建ChangeNotifierProvider
/// 3.在其他位置共享数据
/// 4.Consumer 修改数据通知更新
//1.创建自己需要共享的数据
class AMCommonViewModel with ChangeNotifier {
int _count = 10;
int get count => _count;
set count(int value) {
_count = value;
// 通知监听者,更新数据
notifyListeners();
}
}
class AMHomePage extends StatefulWidget {
const AMHomePage({Key? key}) : super(key: key);
@override
_AMHomePageState createState() => _AMHomePageState();
}
class _AMHomePageState extends OSState<AMHomePage> {
var listener;
@override
void initState() {
// TODO: implement initState
super.initState();
OSNavigator.getInstance().addListener(this.listener = (current, pre) {
print("当前页面:${current.page}");
print("上一个页面:${pre.page}");
});
}
@override
void dispose() {
// TODO: implement dispose
OSNavigator.getInstance().removeListener(this.listener);
super.dispose();
}
// 变量声明在 build方法外面,如果在build内部声明,重新build每次都会声明,相当于变量永远是新的,值永远是初始化的值
Widget build(BuildContext context) {
/// 2.在程序的顶层创建ChangeNotifierProvider(我这里仅限HomePage,如果需要最顶层,可以包裹runApp)
return ChangeNotifierProvider(
create: (ctx) => AMCommonViewModel(),
child: Scaffold(
appBar: AppBar(
title: Text("逻辑资源"),
),
body: Column(
children: [
Container(
height: 110,
width: double.infinity,
child: Card(
color: Colors.orange,
child: Column(
children: [
MaterialButton(
color: Colors.redAccent,
textColor: Colors.white,
onPressed: () {
OSNavigator.getInstance().onJumpTo(
RouteStatus.homeDetail,
args: {"videoModel": VideoModel(180)});
},
child: Text("点击跳转详情"),
),
Selector<AMCommonViewModel, AMCommonViewModel>(
selector: (ctx, countVM) => countVM,
shouldRebuild: (prev, next) => false,
//优化child不重建
child: Text("计数器+1"),
builder: (ctx, countVM, child) {
return MaterialButton(
color: Colors.redAccent,
textColor: Colors.white,
onPressed: () {
/// 修改数据
setState(() {
countVM.count += 1;
});
},
child: child,
);
},
),
],
),
),
),
AMCardView01(),
AMCardView02()
],
),
),
);
}
}
class AMCardView01 extends StatelessWidget {
const AMCardView01({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
///3.在其他位置共享数据
var resCount = Provider.of<AMCommonViewModel>(context).count;
return Container(
height: 80,
width: double.infinity,
child: Card(
color: Colors.orange,
child: Column(
children: [
Center(
child: Text("当前的数量为$resCount"),
)
],
),
),
);
}
}
class AMCardView02 extends StatelessWidget {
///3.在其他位置共享数据
const AMCardView02({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
var resCount = Provider.of<AMCommonViewModel>(context).count;
return Container(
height: 80,
width: double.infinity,
child: Card(
color: Colors.yellow,
child: Column(
children: [
Center(
child: Text("当前的数量为$resCount"),
)
],
),
),
);
}
}
效果图
文章目录
关闭
共有 0 条评论