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 构建的解耦。

相关推荐
智江鹏6 分钟前
Android 之 Kotlin 和 MVVM 架构的 Android 登录示例
android·开发语言·kotlin
凛_Lin~~34 分钟前
2025-08 安卓开发面试拷打记录(面试题)
android
牛巴粉带走1 小时前
Flutter 构建失败:watchOS Target 类型无法识别的解决记录
flutter·ios·apple watch
网安Ruler1 小时前
Web开发-PHP应用&文件操作安全&上传下载&任意读取删除&目录遍历&文件包含
android
aningxiaoxixi2 小时前
android audio 之 Engine
android·前端·javascript
教程分享大师2 小时前
带root_兆能ZN802及兆能ZNM802融合终端安卓9系统线刷机包 当贝纯净版
android·电脑
whysqwhw2 小时前
Android硬件加速全景解析与深度优化指南
android
TralyFang2 小时前
Flutter listview的复用与原生有什么区别
flutter
whysqwhw3 小时前
RecyclerView 快速滑动场景优化 Bitmap 加载
android