多个ChangeNotifierProxyProvider更新ChangeNotifier失效修复
问题原因
你的判断完全正确,当前写法会创建两个独立的C实例。MultiProvider中同类型的Provider后注册的会覆盖前一个的注入,最终只有ChangeNotifierProxyProvider<B, C>的逻辑生效,A的变更永远不会触发C的更新。
标准修复方案
Provider官方原生提供了支持多依赖源的ProxyProvider变体,依赖2个状态时直接使用ChangeNotifierProxyProvider2即可,整个注入链只会创建一个C实例,A或B任意一个发生变更都会触发update回调:
MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => A()), ChangeNotifierProvider(create: (context) => B()), ChangeNotifierProxyProvider2<A, B, C>( create: (context) => C(), update: (_, a, b, c) => c! ..updateFromA(a) ..updateFromB(b), ), ], child: const MyApp(), )
这类多依赖ProxyProvider官方提供了从
ProxyProvider2到ProxyProvider6的不同版本,覆盖绝大多数少依赖场景,不需要重复注册同一类型的Provider。
灵活替代方案
如果依赖的状态数量超过6个,或者不想写过长的泛型声明,可以采用C内部自监听的实现方式:
- 在C的构造函数中传入A、B的实例引用
- C初始化时主动给A、B添加变更监听器
- C销毁时移除监听器避免内存泄漏
首先是C类的实现代码:
class C extends ChangeNotifier { final A a; final B b; C({required this.a, required this.b}) { // 初始化时同步一次两个依赖的初始值 updateFromA(a); updateFromB(b); // 注册变更监听 a.addListener(_onAChanged); b.addListener(_onBChanged); } void _onAChanged() => updateFromA(a); void _onBChanged() => updateFromB(b); // 原有的业务更新逻辑 void updateFromA(A a) { // 自定义业务处理 notifyListeners(); } void updateFromB(B b) { // 自定义业务处理 notifyListeners(); } @override void dispose() { // 必须移除监听,否则会造成内存泄漏 a.removeListener(_onAChanged); b.removeListener(_onBChanged); super.dispose(); } }
对应的Provider注册代码:
MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => A()), ChangeNotifierProvider(create: (context) => B()), ChangeNotifierProvider( create: (context) => C( a: context.read<A>(), b: context.read<B>(), ), ), ], child: const MyApp(), )
方案选择建议
- 依赖数量在6个以内时,优先使用对应参数数量的
ChangeNotifierProxyProviderN,不需要手动处理监听器的注册和释放,代码更简洁也不容易出错 - 依赖数量多、或者C本身需要长期持有其他状态的引用时,选择自监听方案灵活度更高
内容的提问来源于stack exchange,提问作者Vadim Kononov
相关产品推荐
相关产品推荐

