Flutter 状态管理
使用provider管理简单的状态
加入依赖:
#数据共享组件 https://github.com/rrousselGit/provider/blob/master/resources/translations/zh-CN/README.md
provider: 6.0.1
首先创建一个简单的实体类:
class User{
///用户名
String username;
///凭证
String accessToken;
User({required this.username, required this.accessToken});
}
ChangeNotifier
用于向监听器发送通知
在修改完相应的状态并且需要更新UI的时候,需要调用notifyListeners();
这个方法。
创建实体类对应的Notifier:
class UserNotifier extends ChangeNotifier {
User _user = User(username: '', accessToken: '');
///设置用户信息
set user(User value) {
_user = value;
notifyListeners();
}
///获取用户信息
User get user => _user;
///退出登录
void logout() {
_user.username = '';
_user.accessToken = '';
notifyListeners();
}
}
ChangeNotifierProvider
ChangeNotifierProvider组件可以向其子孙结点暴露ChangeNotifier的一个实例
需要放置在使用状态管理的最上层组件之上
通常放在MyApp上面,用于管理全局状态:
runApp(
ChangeNotifierProvider(
create: (BuildContext context) => UserNotifier(),
child: const MyApp(),
)
);
这里的UserNotifier只会被实例化一次
如果想提供更多的状态,可以使用MultiProvider:
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => CartModel()),
Provider(create: (context) => SomeOtherClass()),
],
child: const MyApp(),
),
);
}
Consumer
用于调用Notifier,在需要使用状态管理组件的外层包裹
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("登录"),
),
body: Center(
child: Consumer<UserNotifier>(builder: (BuildContext context, user, child) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Consumer<UserNotifier>(builder: (BuildContext context, user, child) {
return Text(user.user.username == '' ? '未登录' : user.user.username);
}),
const SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () {
user.logout();
},
child: const Text("注销"))
],
);
}),
),
);
}
需要使用泛型指定要访问的模型类型:Consumer<UserNotifier>
第二个参数user就是UserNotifier的实例
第三个参数用于优化,如果Consumer下面有一个庞大的子树,不需要根据状态改变,就可以在child中创建一次,然后通过builder获取该child,放到相应的位置:
return Consumer<CartModel>(
builder: (context, cart, child) => Stack(
children: [
// Use SomeExpensiveWidget here, without rebuilding every time.
if (child != null) child,
Text("Total price: ${cart.totalPrice}"),
],
),
// Build the expensive widget here.
child: const SomeExpensiveWidget(),
);
Provider.of
有的时候你不需要模型中的 数据 来改变 UI,但是你可能还是需要访问该数据。比如,ClearCart
按钮能够清空购物车的所有商品。它不需要显示购物车里的内容,只需要调用 clear()
方法。
我们可以使用 Provider.of
,并且将 listen
设置为 false
。
Provider.of<CartModel>(context, listen: false).removeAll();
在 build 方法中使用上面的代码,当 notifyListeners
被调用的时候,并不会使 widget 被重构。
本文来自博客园,作者:Bin_x,转载请注明原文链接:https://www.cnblogs.com/Bin-x/p/15538876.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)