Flutter Provider 用法总结(更新中...)

Flutter Provider 用法总结(含 ChangeNotifierProvider、Consumer、ChangeNotifierProxyProvider, BlocListener, BlocBuilder)


1. ChangeNotifierProvider

  • ChangeNotifierProvider<T> 是最常用的 Provider,作用是在 Widget 树中提供一个 T 类型(通常为 ChangeNotifier)的实例,供其子 Widget 访问和监听。
  • 用法示例:
dart 复制代码
ChangeNotifierProvider<SkinSelectNotifier>(
  create: (_) => SkinSelectNotifier(widget.vehicle),
  child: ...
)
  • 上面代码会用 widget.vehicle 创建一个新的 SkinSelectNotifier 实例,并将其注入到子 Widget 树中。

2. Consumer

  • Consumer<T> 是 Provider 体系中用于监听并响应 T 类型 Provider 状态变化的 Widget。
  • 只要 Provider 中的数据有变化,builder 就会自动重建。
  • 用法示例:
dart 复制代码
Consumer<SkinSelectNotifier>(
  builder: (_, value, __) {
    // value 就是最新的 SkinSelectNotifier 实例
    // 只要 SkinSelectNotifier.notifyListeners 被调用,builder 就会刷新
  }
)

3. ChangeNotifierProxyProvider

3.1 作用

  • ChangeNotifierProxyProvider<A, B> 用于创建一个 B 类型(ChangeNotifier),并让它可以依赖于另一个 Provider A 的变化。
  • 当 A 发生变化时,B 可以自动获得最新的 A 实例,及时更新自身状态。

3.2 create 和 update 的区别

  • create:首次在 Widget 树中创建 B(ChangeNotifier)实例时调用。只执行一次。
  • update:每当 A(依赖的 Provider)发生变化,或 Provider 热重载/依赖变化时都会被调用。会多次执行。

3.3 推荐写法

dart 复制代码
ChangeNotifierProxyProvider<MyModel, MyChangeNotifier>(
  create: (_) => MyChangeNotifier(),
  update: (_, myModel, myNotifier) => myNotifier..update(myModel),
)
  • 解释
    • create 只负责实例化 MyChangeNotifier。
    • update 保证每次 MyModel 变化时,将最新的 MyModel 注入 MyChangeNotifier,并复用旧实例。
⚠️ 注意事项
  • 不要update 内直接 new 出新的 B,否则之前的数据和状态会丢失。
  • 推荐在 B 内部实现 update 方法,用于同步依赖变化。

4. 应用场景举例

  • 如果你的 ChangeNotifier 需要依赖于别的 Provider(如用户信息、配置、全局事件流),优先使用 ChangeNotifierProxyProvider
  • 如果只是需要一个简单的可变状态管理,直接用 ChangeNotifierProvider 即可。

5. BlocListener 的 listenWhen 与 BlocBuilder 的关系总结

5.1 listenWhen 是什么?什么时候触发?

  • listenWhenBlocListener 的一个可选回调函数,签名如下:
dart 复制代码
bool listenWhen(previous, current)
  • 每当 Bloc 的状态发生变化时,listenWhen 会被调用一次,传入前一个状态 previous 和当前状态 current
  • 若返回 true,则会执行 listener 回调。
  • 若返回 false,则不执行。

5.2 listenWhen 的用途

用于过滤监听条件,避免每次状态变化都触发副作用,只在关心的状态变化时执行。例如:

dart 复制代码
listenWhen: (previous, current) {
  final isActualLogin = previous.user == null && current.user != null;
  final shouldListen = isActualLogin && (current.action is LoginAction);
  return shouldListen || previous != current;
}

表示:

  • 用户从未登录到已登录,并且 action 是 LoginAction 时触发
  • 或者状态有变化时触发

5.3 返回 true / false 会怎样?

  • 返回 true:执行 listener: (context, state) { ... }
  • 返回 false:不会执行 listener

5.4 BlocListener 和 BlocBuilder 的区别与关系

对象 作用 是否重建 UI 是否执行副作用 有条件过滤功能
BlocListener 执行副作用(如导航) 使用 listenWhen
BlocBuilder 构建 UI 使用 buildWhen
  • BlocListener 不负责 UI 构建,只在特定状态变化时做出响应。
  • BlocBuilder 始终对状态变化做出响应(除非使用 buildWhen 过滤)。
  • listenWhenbuildWhen 可以搭配使用,实现精细控制。

总结

  • listenWhen 用于决定 BlocListener 的 listener 是否触发。
  • 返回 true 会执行副作用逻辑,false 不执行。
  • BlocBuilder 总是响应 Bloc 状态变化,和 listenWhen 无关,若要过滤 UI 重建需使用 buildWhen。
  • 二者搭配使用能实现副作用处理和 UI 构建的解耦。

相关推荐
氦客13 分钟前
Android Compose 图层的合成 : BlendMode
android·compose·jetpack·layer·blendmode·graphics·图层的合成
5008434 分钟前
HCCL 集合通信编程:多卡协同的正确姿势
java·flutter·性能优化·electron·wpf
Sahadev_1 小时前
GitMemo 安卓版发布了:现在可以随时随地查看和记录自己的笔记
android·笔记·创业创新
龙之叶1 小时前
Android 12:在 ActivityStarter 层拦截分享、搜索与 HTTP 外链
android·chrome·http
牛奔2 小时前
Android 开发通用解决方案:使用 ADB 彻底卸载已安装 App(解决版本降级安装失败问题)
android·adb
tryqaaa_2 小时前
学习日志(三)【php语法学习,iscc校赛wp】
android·网络协议·学习·安全·web安全·web
你听得到113 小时前
从 Figma 走查到 AI 可验证产物:我如何重构客户端 UI 交付链路
前端·vue.js·flutter
plainGeekDev3 小时前
Kotlin协程面试题:suspend原理都说不清,协程你真会用?
android·面试·kotlin
Kapaseker3 小时前
Android 官方开始拥抱 WebView
android
ujainu小3 小时前
CANN hixl:大模型 PD 分离场景的零拷贝通信库
android·java·缓存