Flutter for OpenHarmony(五) 状态管理小计
在 Flutter 中,状态(State) 是指在应用运行时可能发生变化的数据。用户输入的文本购物车中的商品数量当前选中的 Tab 页面从网络加载的数据Flutter 的 UI 是声明式的:当状态发生变化时,框架会重新构建受影响的 Widget 树,以更新界面。状态管理 的本质是:高效、安全地在 Widget 树的不同层级之间共享和更新状态,同时避免不必要的重建,提升性能并保持代码清晰。Provi
题记
从配置,到表单、到网络请求,已经写了好几篇
今天就是总结加上填坑。
之前写简单表单的时候使用了Provider状态管理,没有说明,本次也是对Provider状态管理的记录。
什么是状态管理
在 Flutter 中,状态(State) 是指在应用运行时可能发生变化的数据。例如:
- 用户输入的文本
- 购物车中的商品数量
- 当前选中的 Tab 页面
- 从网络加载的数据
Flutter 的 UI 是声明式的:当状态发生变化时,框架会重新构建受影响的 Widget 树,以更新界面。
状态管理 的本质是:
高效、安全地在 Widget 树的不同层级之间共享和更新状态,同时避免不必要的重建,提升性能并保持代码清晰。
为什么选择 Provider?
- 官方推荐(flutter.dev 文档明确推荐)
- 无需 Boilerplate 代码
- 自动处理 Widget 的生命周期(避免内存泄漏)
- 支持多种状态共享方式(ChangeNotifier、ValueNotifier、Future、Stream 等)
- 与 devtools 完美集成,便于调试
- 学习成本低,5 分钟即可上手
安装Provider
flutter pub add provider
看到pubspec.yaml 文件中已经存在了。
声明数据仓库
它是负责存放数据和更新数据的地方。
import 'package:flutter/material.dart';
import 'package:harmony_sqllite_floor_demo/models/user_model.dart';
import 'package:uuid/uuid.dart';
/// 用户数据状态管理类
/// 继承自 [ChangeNotifier] 以支持 Provider 的状态更新通知机制
class UserProvider extends ChangeNotifier {
// 内部私有的用户列表,存放在内存中
final List<User> _users = [];
// 用于生成唯一标识符的服务
final _uuid = const Uuid();
/// 获取所有用户(只读)
/// 使用 List.unmodifiable 确保外部不能直接通过 users.add() 修改列表,
/// 必须通过本类提供的方法来更新数据,从而保证 notifyListeners() 能被触发。
List<User> get users => List.unmodifiable(_users);
/// 添加新用户
/// [account] 账号, [password] 密码, [nickname] 昵称, [remarks] 备注, [option] 标签选项
void addUser({
required String account,
required String password,
required String nickname,
required String remarks,
required UserOption option,
}) {
final user = User(
id: _uuid.v4(), // 自动生成随机 ID
account: account,
password: password,
nickname: nickname,
remarks: remarks,
option: option,
);
_users.add(user);
// 📢 极其重要:通知所有正在监听(Consumer)的 UI 界面进行刷新
notifyListeners();
}
/// 更新用户信息
/// 通过 [updatedUser.id] 查找并替换现有的用户对象
void updateUser(User updatedUser) {
final index = _users.indexWhere((u) => u.id == updatedUser.id);
if (index != -1) {
_users[index] = updatedUser;
// 通知 UI 界面,该用户信息已变更
notifyListeners();
}
}
/// 删除用户
/// 根据 [id] 从列表中移除匹配的用户
void deleteUser(String id) {
_users.removeWhere((u) => u.id == id);
// 通知 UI 界面,列表已变短,需要重新渲染
notifyListeners();
}
}
注册这个仓库
你必须在 App 启动时告诉系统:“这是我的仓库, 任何风吹草动必须记录在案,同时通知给我”。
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserProvider()), // 挂起这个大屏幕
],
child: const MyApp(),
),
);
修改以及更新
- 修改
// 注意:这里用的是 context.read 而不是 Consumer。
// 区别是:
// - Consumer 是“我在看这个数据,变了请告诉我”(用于 UI 刷新)。
// - context.read 是“我只是要用一下仓库的功能,别管我”(用于点击事件、一次性操作)。
// 因为这里是点击按钮后执行的一个动作,不需要监听后续的变化,所以 read 更省资源。
final provider = context.read<UserProvider>();
if (widget.user == null) {
// 3a. 如果是新用户,调用仓库的“添加”功能
provider.addUser(
account: _accountController.text,
password: _passwordController.text,
nickname: _nicknameController.text,
remarks: _remarksController.text,
option: _selectedOption,
);
} else {
// 3b. 如果是编辑旧用户,调用仓库的“更新”功能
provider.updateUser(
widget.user!.copyWith(
account: _accountController.text,
password: _passwordController.text,
nickname: _nicknameController.text,
remarks: _remarksController.text,
option: _selectedOption,
),
);
}
- 更新数据
// 【重点】Consumer 是 Provider 插件提供的核心组件,翻译过来叫“消费者”。
// 它的作用是:当 UserProvider(数据源)里的数据发生变化(调用了 notifyListeners)时,
// Consumer 会自动标记它的 builder 函数内部的代码为“过期”,并命令 Flutter 重新运行这段代码。
body: Consumer<UserProvider>(
// builder 是 Consumer 的核心构造器。
// context: 上下文(Flutter 树中的位置)。
// provider: 就是我们注册的 UserProvider 实例,通过它可以直接读到里面的数据。
// child: 一个优化项,如果某些不随数据变化的 UI 放在这里,可以避免重复渲染。
builder: (context, provider, child) {
// 1. 判断仓库里的用户列表是否为空
if (provider.users.isEmpty) {
return const Center(child: Text('暂无数据'));
}
// 2. 如果仓库里有货(有用户数据),我们就用 ListView 显示出来
return ListView.builder(
itemCount: provider.users.length, // 告诉列表一共有多少个人
itemBuilder: (context, index) {
// 3. 从 provider(仓库)中取出第 index 个用户
final user = provider.users[index];
// 4. 将提取出的单个用户交给专门负责显示单行的视图组件 (_UserListItem)
return _UserListItem(user: user);
},
);
},
),
到这里我们的整个流程已经很清晰的展示出来了,首先是需要声明一个需要存储数据的仓库,然后在 runapp 的时候注册一下。声明 Provider 的变量 provider = context.read<UserProvider>(), 进行交互的时候 使用 provider调用仓库中声明的变量,然后使用Consumer 进行监控实时更新数据。
需要注意的是,自动刷新的原理:数据变化触发 notifyListeners 后,Consumer 才能自动重新构建 UI,如果只是执行数据,函数的末尾不执行 notifyListeners 也是不行的。
我们看下具体的效果(其实之前演示过了 偷个懒在)
我在第一幕的列表页面进行监听,在第二幕中,调用了 addUser 的方法。返回第一幕的时候,数据已经展示到列列表页面了。
总结
Provider 适合的场景:
中小型应用、快速原型、中等复杂度的状态共享需求。
进阶学习路径:
熟练掌握 ChangeNotifierProvider + Consumer
学习 ProxyProvider 和 MultiProvider
尝试 FutureProvider / StreamProvider
了解 Riverpod(Provider 2.0 版本,推荐新项目使用)
对比 Bloc、Redux 等方案,选择适合团队的方案
希望本文能帮助您快速上手 Flutter 的状态管理。如果您正在开发一个具体功能(例如购物车、表单、主题切换),欢迎提供更多细节,我可以为您编写更针对性的 Provider 示例代码。
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)