目录
应该怎么选
Consumer、Selector、Widget 拆分、const,应该怎么选择?当页面发生重建时,应该优先用哪种优化方式?
1、选择顺序
需要监听数据?
│
▼
能拆 Widget 吗?
│ │
能 不能
│ │
▼ ▼
拆 Widget 使用 Consumer
│
▼
是否只关心部分字段?
│
┌─────┴─────┐
│ │
否 是
│ │
▼ ▼
watch Selector
最后如果Widget完全静态加:const。
Consumer适合: 当前 Widget 自己不能 watch。比如AppBar的title更新
AppBar(
title: ?
)
所以Consumer更多是: 无法拆 Widget 时的补救方案。
Selector适用于: 一个 Notifier 很大,但 Widget 只关心其中一个字段。
const不能阻止父 Widget build。 它优化的是:在updateChild方法中直接返回oldElement,根本不用调用canUpdateWidget。
2、企业项目中,我建议遵循的四条原则
Page 尽量不要 watch(),让最小业务 Widget 去 watch()。(就是watch不要放的太高)
先拆 Widget,再考虑 Consumer。
Consumer 放得越低越好,不要把整个页面包进去。
只有当一个 Notifier 很大,而 Widget 只关心其中一小部分数据时,再使用 Selector。
如果真正做到这四点,绝大多数 Provider 页面都能获得很好的性能,而代码结构也会更加清晰、易维护。
Notifier 应该如何拆分?(企业级架构)
一、企业经验
第一条
一个 Notifier 负责一个业务领域(Business Domain)。
不要负责整个页面。更不要负责整个App。
第二条
生命周期不同的数据,不要放进同一个 Notifier。
例如:Theme 整个 App。SearchKeyword 进入页面才有。
第三条
高频变化的数据,尽量独立。
例如:购物车数量,聊天未读数,股票行情这种每秒notify。不要跟用户信息放一起。
第四条
不要为了减少 Notifier 数量而合并业务。
其实恰恰相反。 Notifier拆得合理notify范围更小,性能反而更好。
二、架构图
App
│
├── Global Provider
│ │
│ ├── UserNotifier
│ ├── ThemeNotifier
│ ├── ConfigNotifier
│
├── Module Provider
│ │
│ ├── ShopNotifier
│ ├── OrderNotifier
│
└── Page Provider
│
├── SearchNotifier
├── EditProfileNotifier
三、Notifier如何通讯
| 场景 | 推荐方案 |
| 一个页面同时操作多个 Provider | UI 层协调 |
| B 业务确实依赖 A 的数据 | ChangeNotifierProxyProvider |
| 大量模块需要响应全局事件 | Event / Stream |
ChangeNotifierProxyProvider<UserNotifier, ChatProvider>(
create: (_) => ChatProvider(),
// 当 UserNotifier 数据改变时,update方法会被执行
update: (BuildContext context, UserNotifier user, ChatProvider? chat) {
chat!.updateUser(user.id);
return chat;
},
)
行者常至,为者常成!