Flutter中借助Riverpod实现主窗口与子窗口状态同步方案咨询
解决Flutter多窗口(desktop_multi_window)与Riverpod共享状态的问题
核心原因
每个Flutter窗口默认会初始化独立的ProviderContainer,这导致主窗口和子窗口的Riverpod状态完全隔离,自然无法同步变更。要实现跨窗口状态共享,必须让所有窗口共用同一个Provider容器。
具体解决方案
1. 定义全局共享的ProviderContainer
在项目中创建一个全局变量保存主窗口初始化的ProviderContainer,确保所有窗口都能访问到它:
// lib/global.dart import 'package:flutter_riverpod/flutter_riverpod.dart'; late final ProviderContainer globalStateContainer;
2. 主窗口使用全局容器启动
修改主窗口的main函数,初始化全局容器并通过UncontrolledProviderScope绑定到App:
// lib/main.dart import 'global.dart'; import 'providers.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter/material.dart'; import 'package:desktop_multi_window/desktop_multi_window.dart'; import 'dart:convert'; void main() { // 初始化全局状态容器 globalStateContainer = ProviderContainer(); runApp( UncontrolledProviderScope( container: globalStateContainer, child: const MainWindowApp(), ), ); } class MainWindowApp extends StatelessWidget { const MainWindowApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('主窗口')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 监听共享状态 Consumer( builder: (context, ref, child) { final count = ref.watch(counterProvider); return Text('当前计数: $count', style: const TextStyle(fontSize: 20)); }, ), const SizedBox(height: 20), // 修改状态的按钮 ElevatedButton( onPressed: () { ref.read(counterProvider.notifier).increment(); }, child: const Text('增加计数'), ), const SizedBox(height: 20), // 创建子窗口按钮 ElevatedButton( onPressed: () async { await DesktopMultiWindow.createWindow(jsonEncode({ 'windowTitle': '子窗口' })) ..setTitle('子窗口') ..show(); }, child: const Text('打开子窗口'), ), ], ), ), ), ); } }
3. 子窗口绑定全局容器
为子窗口创建独立的入口文件(比如lib/child_main.dart),同样使用全局容器启动App:
// lib/child_main.dart import 'global.dart'; import 'providers.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter/material.dart'; void main() { runApp( UncontrolledProviderScope( container: globalStateContainer, child: const ChildWindowApp(), ), ); } class ChildWindowApp extends StatelessWidget { const ChildWindowApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('子窗口')), body: Center( child: Consumer( builder: (context, ref, child) { final count = ref.watch(counterProvider); return Text('主窗口同步计数: $count', style: const TextStyle(fontSize: 20)); }, ), ), ), ); } }
4. 配置子窗口入口
在pubspec.yaml中指定子窗口的入口文件,让desktop_multi_window能正确启动子窗口:
flutter: desktop_multi_window: entry_points: - lib/child_main.dart
5. 定义共享状态Provider
示例中使用的共享计数器Provider:
// lib/providers.dart import 'package:flutter_riverpod/flutter_riverpod.dart'; final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) { return CounterNotifier(); }); class CounterNotifier extends StateNotifier<int> { CounterNotifier() : super(0); void increment() { state++; } }
关键注意事项
- 确保所有窗口都使用同一个ProviderContainer,禁止各自创建独立容器。
- 由于desktop_multi_window是单进程多窗口模式,全局变量是安全且高效的状态共享方式。
- 如果使用
AsyncNotifier或其他异步状态,同样遵循此方案,无需额外修改。
内容的提问来源于stack exchange,提问作者Ben Alex
相关产品推荐
相关产品推荐

