Flutter多Provider场景下如何实现数据共享与跨Provider方法调用
方案说明
你提到的ChangeNotifierProxyProvider完全可以满足多个子Provider访问AppService的需求,同时也支持在子Provider中调用AppService的公开方法,具体改造步骤如下:
步骤1:给AppService添加公开访问的getter
你当前AppService中的_sessionId、_name是私有属性,外部无法直接访问,需要先添加getter暴露:
class AppService with ChangeNotifier { String _sessionId; String _name; // 新增公开getter String get sessionId => _sessionId; String get name => _name; // 你原来的其他公开方法示例 void someAppMethod() { // 业务逻辑 notifyListeners(); } ... }
步骤2:改造子Service,通过构造函数接收AppService实例
以ServiceB为例,ServiceC、ServiceD改造逻辑一致:
class ServiceB with ChangeNotifier { // 保存AppService实例 final AppService appService; // 构造函数注入AppService ServiceB(this.appService); void testAccess() { // 直接访问AppService的属性 print(appService.sessionId); print(appService.name); // 直接调用AppService的公开方法 appService.someAppMethod(); } ... }
步骤3:修改Provider初始化配置
有两种实现方式,可根据你的业务场景选择:
方式1:直接在create时读取AppService(适合AppService实例不会被替换的场景,写法更简单)
MultiProvider( providers: [ ChangeNotifierProvider<AppService>( create: (_) => AppService(), ), ChangeNotifierProvider<ServiceB>( // 利用create的context参数读取已初始化的AppService create: (context) => ServiceB(context.read<AppService>()), ), ChangeNotifierProvider<ServiceC>( create: (context) => ServiceC(context.read<AppService>()), ), ChangeNotifierProvider<ServiceD>( create: (context) => ServiceD(context.read<AppService>()), ), ], child: const InitSysApp(), )
方式2:使用ChangeNotifierProxyProvider(适合AppService实例可能更新,需要子Provider同步响应的场景)
MultiProvider( providers: [ ChangeNotifierProvider<AppService>( create: (_) => AppService(), ), ChangeNotifierProxyProvider<AppService, ServiceB>( create: (context) => ServiceB(context.read<AppService>()), // AppService更新时会触发update,给ServiceB传入最新的AppService实例 update: (context, appService, previousServiceB) => previousServiceB!..appService = appService, ), // ServiceC、ServiceD同理配置 ChangeNotifierProxyProvider<AppService, ServiceC>( create: (context) => ServiceC(context.read<AppService>()), update: (context, appService, previous) => previous!..appService = appService, ), ChangeNotifierProxyProvider<AppService, ServiceD>( create: (context) => ServiceD(context.read<AppService>()), update: (context, appService, previous) => previous!..appService = appService, ), ], child: const InitSysApp(), )
注意:如果选择方式2,需要给子Service的appService属性去掉final修饰,支持更新赋值
补充说明
- 子Provider完全可以调用AppService的公开方法,只要方法没有私有下划线修饰,都可以通过注入的appService实例直接调用。
- 如果需要AppService的属性变化时,子Provider也同步更新状态,可以在ProxyProvider的update方法中调用子Provider的更新逻辑,再执行
notifyListeners()即可。
内容的提问来源于stack exchange,提问作者teh_raab
相关产品推荐
相关产品推荐

