Flutter Provider 在 OpenHarmony 项目中的状态管理实践
本文分享了在OpenHarmony项目中采用Provider进行Flutter状态管理的实践经验。随着项目复杂度增加,原生setState方法导致页面频繁刷新、状态同步困难等问题日益突出。作者通过引入Provider状态管理方案,将应用状态拆分为UserProvider、CartProvider等独立模块,使用Consumer和Selector优化局部刷新,显著提升了应用性能,特别是在OpenHa
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
Flutter Provider 在 OpenHarmony 项目中的状态管理实践
前言
最近这段时间一直在做 Flutter for OpenHarmony 的适配项目,随着页面越来越多,我发现一个问题开始变得明显:
页面状态越来越不好管理了。
一开始项目比较简单的时候,其实直接:
setState()
也能跑。
但后面随着:
- 首页
- 用户中心
- 商品详情
- 购物车
- 消息页
这些模块逐渐加进来之后,状态开始变乱。
最明显的问题包括:
- 页面之间数据同步困难
- 多层 Widget 传参
- 页面刷新范围过大
- rebuild 过于频繁
- 代码越来越难维护
后来我把项目状态管理统一迁移到了 Provider,整体结构清晰了不少,而且在 OpenHarmony 真机上的页面稳定性也好了很多。
这篇文章主要记录一下这次状态管理改造过程。
一、为什么最后选择 Provider
Flutter 状态管理方案其实很多。
常见的:
| 方案 | 特点 |
|---|---|
| setState | 简单 |
| Provider | 官方推荐 |
| GetX | 上手快 |
| Riverpod | 功能强 |
| Bloc | 适合大型项目 |
我最后选 Provider 的原因比较现实:
- 官方生态成熟
- 学习成本低
- Flutter 社区资料多
- 适合中型项目
- 对现有项目改动不算太大
而且 Flutter 官方很多示例本身也在用 Provider。
对于 OpenHarmony 项目来说:
稳定其实比“炫技”更重要。
二、项目里最开始的问题
先说一下我之前的代码结构。
页面层层传参
比如首页用户信息:
HomePage(
user: user,
)
然后:
BodyWidget(
user: user,
)
接着:
InfoCard(
user: user,
)
参数一路往下传。
页面层级一多之后:
代码非常难维护。
setState 到处都是
例如:
setState(() {
cartCount++;
});
刚开始问题不大。
但后面:
购物车、消息数、用户信息
这些全局状态越来越多。
整个页面会开始频繁 rebuild。
三、接入 Provider
1. 添加依赖
dependencies:
provider: ^6.1.2
执行:
flutter pub get
四、创建状态类
这里我先拿用户信息举例。
UserProvider
class UserProvider extends ChangeNotifier {
String name = "";
void updateName(String value) {
name = value;
notifyListeners();
}
}
核心其实就两部分:
- 数据
- notifyListeners()
五、全局注入 Provider
在项目入口:
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => UserProvider(),
),
],
child: const MyApp(),
),
);
}
这样后面页面里就能直接获取状态。
六、页面读取状态
1. 最基础写法
final userProvider =
Provider.of<UserProvider>(context);
读取:
Text(userProvider.name)
更新:
userProvider.updateName("Tom");
七、我在 OpenHarmony 项目里遇到的一个问题
这个问题我刚开始其实没太注意。
问题现象
页面频繁 rebuild。
例如:
修改购物车数量后:
整个首页都刷新了。
包括:
- Banner
- 列表
- 用户信息
全部重新 build。
在鸿蒙设备上:
卡顿会比 Android 更明显一点。
原因
我当时直接:
Provider.of<UserProvider>(context)
默认:
listen: true
也就是说:
状态变化后整个 Widget 都会刷新。
八、后来的优化方案
1. 使用 Consumer
后来我改成:
Consumer<UserProvider>(
builder: (_, provider, __) {
return Text(provider.name);
},
)
这样只有 Consumer 内部刷新。
效果会好很多。
2. 使用 Selector
后面进一步优化:
Selector<UserProvider, String>(
selector: (_, provider) {
return provider.name;
},
builder: (_, name, __) {
return Text(name);
},
)
这个优化在复杂页面里挺明显。
尤其 OpenHarmony 真机测试时:
rebuild 次数下降很多。
九、不要把所有状态都放一个 Provider
这个坑我后面踩得挺深。
错误结构
class AppProvider extends ChangeNotifier {
UserModel user;
List cartList;
bool darkMode;
int msgCount;
}
刚开始图方便。
结果后面:
任何一个状态变化。
整个页面树都在刷新。
后来的拆分方案
UserProvider
CartProvider
ThemeProvider
MessageProvider
每个模块单独管理。
后面维护会轻松很多。
十、Provider 和页面生命周期问题
这里有个我在鸿蒙设备上实际碰到的问题。
问题
页面 initState 里直接读取 Provider:
@override
void initState() {
super.initState();
final userProvider =
Provider.of<UserProvider>(context);
}
直接报错:
dependOnInheritedWidgetOfExactType
正确方式
Provider.of<UserProvider>(
context,
listen: false,
)
或者:
WidgetsBinding.instance
.addPostFrameCallback((_) {
});
这个问题 Flutter 本身就有。
但 OpenHarmony 调试时会更容易暴露。
十一、购物车模块的一个实际优化
购物车是我这次改造里变化最大的地方。
优化前
点击商品:
setState(() {
cartCount++;
});
整个页面刷新。
列表明显掉帧。
优化后
context.read<CartProvider>()
.addGoods(goods);
购物车角标:
Consumer<CartProvider>(
builder: (_, provider, __) {
return Text(
provider.count.toString(),
);
},
)
最终:
只有角标刷新。
页面流畅很多。
十二、我的最终项目结构
后面项目里我基本统一成:
providers/
├── user_provider.dart
├── cart_provider.dart
├── theme_provider.dart
└── message_provider.dart
业务层:
pages/
services/
models/
widgets/
整体会清晰很多。
十三、实际效果
改造前:
| 问题 | 表现 |
|---|---|
| 页面 rebuild | 高频 |
| 状态同步 | 混乱 |
| 多层传参 | 严重 |
| 页面卡顿 | 存在 |
改造后:
| 项目 | 效果 |
|---|---|
| 页面刷新 | 更精准 |
| 代码结构 | 更清晰 |
| 页面流畅度 | 提升明显 |
| 状态维护 | 更容易 |
目前这个方案已经在 OpenHarmony 项目里稳定用了挺长时间。
十四、总结
这次做 Flutter Provider 状态管理改造,一个比较深的感受是:
Flutter 项目到后期,真正难维护的往往不是 UI。
而是状态。
尤其是跨平台项目:
如果状态管理混乱:
后面定位问题会非常痛苦。
Provider 虽然不是最“高级”的方案。
但:
- 足够稳定
- 学习成本低
- 社区成熟
- 很适合业务项目
对于 Flutter for OpenHarmony 这种场景,其实挺合适。
后面我也准备继续研究:
- Riverpod 在 OpenHarmony 下的表现
- Flutter 状态持久化
- Provider + 网络层结合
- 大型项目状态拆分方案
希望这篇文章能给正在做 Flutter for OpenHarmony 项目的同学一点参考。
更多推荐
所有评论(0)