Flutter Getx Providers重复初始化问题求助
解决GetX Providers重复初始化问题
问题现象
使用GetX包管理应用状态时,所有Providers被多次初始化,控制台输出重复的实例创建日志,同时出现Firebase后台隔离重复启动警告。
现有代码实现
主入口初始化代码
Future<void> main() async { WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); ErrorWidget.builder = (e) => ErrorScreen(e.exception); await App.initializeProviders(); if (Get.find<AuthProvider>().isAuth) await App.initializeUserProviders(); runApp(const Appi()); } class Appi extends StatelessWidget { const Appi({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container(); } }
核心Providers初始化方法
static initializeProviders() async { try { Get.lazyPut<AuthProvider>(() => AuthProvider(), fenix: true); Get.lazyPut<SettingsProvider>(() => SettingsProvider(), fenix: true); Get.put<NotificationsProvider>(NotificationsProvider(), permanent: true); await Get.find<AuthProvider>().load(); await Get.find<SettingsProvider>().load(); await FirebasePlugin.initializeApp(); } catch (e) { print(e); } }
已认证用户专属Providers初始化方法
static initializeUserProviders() async { try { Get.lazyPut<MainProvider>(() => MainProvider(), fenix: true); Get.lazyPut<FiltersProvider>(() => FiltersProvider(), fenix: true); Get.lazyPut<CartProvider>(() => CartProvider(), fenix: true); Get.lazyPut<SearchProvider>(() => SearchProvider(), fenix: true); // Get.lazyPut(() => HomeProvider(), fenix: true); // Get.find<HomeProvider>().load(); Get.find<NotificationsProvider>().load(); Get.find<FiltersProvider>().load(); Get.find<CartProvider>().load(); } catch (e) { // } }
控制台输出日志
[GETX] Instance "NotificationsProvider" has been created [GETX] Instance "NotificationsProvider" has been initialized 2[GETX] Instance "AuthProvider" has been created 2[GETX] Instance "AuthProvider" has been initialized [GETX] Instance "NotificationsProvider" has been created [GETX] Instance "NotificationsProvider" has been initialized [GETX] Instance "AuthProvider" has been created [GETX] Instance "AuthProvider" has been initialized 2[GETX] Instance "SettingsProvider" has been created 2[GETX] Instance "SettingsProvider" has been initialized [GETX] Instance "SettingsProvider" has been created [GETX] Instance "SettingsProvider" has been initialized 2 W/FLTFireMsgService( 5927): Attempted to start a duplicate background isolate. Returning...
各Provider的load方法
AuthProvider.load()
Future<void> load() async { if (_profile.value != null && _token.value != null) return; final localStorage = await SharedPreferences.getInstance(); final lt1 = localStorage.getString('somekey1'); final lt2 = localStorage.getString('somekey2'); final lt3 = localStorage.getString('somekey3'); final localProfile = localStorage.getString('_up'); if (lt1 != null && lt2 != null && lt3 != null && localProfile != null) { _token.value = lt1 + lt2 + lt3; final profile = json.decode(localProfile); _profile.value = UserModel.fromJson(profile, avatar: profile['avatar']); update(); return; } }
FiltersProvider.load()
load() async { await App.getData('PRD/filters.php').then((value) { if (value != null) { final platforms = value["brands"] as Map<String, dynamic>; final stores = value["stores"] as Map<String, dynamic>; setFilters(stores.values.toList(), platforms.values.toList()); } }).catchError((e) { throw e; // TODO:: handle error }); } void setFilters( List<dynamic> stores, List<dynamic> platforms, { bool local = false, }) { if (stores.isEmpty || platforms.isEmpty) return; _allPlatforms.value.clear(); _allStores.value.clear(); _allPlatforms.value.add(Filter.getDefault(isPlatform: true)); _allStores.value.add(Filter.getDefault()); for (var platform in platforms) { _allPlatforms.value.add(Filter.fromJson(platform, isPlatform: true)); } for (var store in stores) { _allStores.value.add(Filter.fromJson(store)); } if (!local) { SharedPreferences.getInstance().then((prefs) { prefs.setString("allPlatforms", jsonEncode(platforms)); prefs.setString("allStores", jsonEncode(stores)); }); } update(); }
NotificationsProvider.load()
Future<void> load() async { final result = await _database.getAll(); if (result.length == _notifications.value.length) return; _notifications.value.clear(); _notifications.value.addAll(result .map((e) => NotificationModel.fromJson({ 'id': e['id'], 'message': e['title'], 'type': e['type'], 'type_id': e['type_id'], 'level': e['level'], 'is_new': e['is_new'], })) .toList()); if (_notifications.value.isNotEmpty) { _notifications.value .sort((a, b) => int.parse(a.id).compareTo(int.parse(b.id))); } update(); }
CartProvider.load()
Future<void> load() async { try { final items = await database.getAll(); _cartItems.clear(); for (var e in items) { _cartItems.add(CartItem.fromJson(e)); } update(); } catch (e) { rethrow; } }
解决方案
1. 检查GetX实例创建逻辑,避免重复注册
在注册Provider前先检查是否已存在实例,避免重复创建;同时用Get.putAsync替代Get.put+手动load,确保实例初始化完成后再存入容器:
// 修改后的核心初始化方法 static initializeProviders() async { try { if (!Get.isRegistered<AuthProvider>()) { Get.lazyPut<AuthProvider>(() => AuthProvider(), fenix: true); } if (!Get.isRegistered<SettingsProvider>()) { Get.lazyPut<SettingsProvider>(() => SettingsProvider(), fenix: true); } if (!Get.isRegistered<NotificationsProvider>()) { await Get.putAsync<NotificationsProvider>(() async { final provider = NotificationsProvider(); await provider.load(); return provider; }, permanent: true); } await Get.find<AuthProvider>().load(); await Get.find<SettingsProvider>().load(); await FirebasePlugin.initializeApp(); } catch (e) { print(e); } }
2. 解决Firebase后台隔离重复问题
给Firebase初始化添加单例判断,避免重复执行:
// 封装Firebase初始化逻辑 static Future<void> initFirebase() async { static bool _initialized = false; if (!_initialized) { await FirebasePlugin.initializeApp(); _initialized = true; } }
3. 优化用户专属Provider初始化逻辑
调用Get.find前先检查实例是否已注册,避免懒加载触发重复创建:
// 修改后的用户专属Provider初始化方法 static initializeUserProviders() async { try { if (!Get.isRegistered<MainProvider>()) { Get.lazyPut<MainProvider>(() => MainProvider(), fenix: true); } if (!Get.isRegistered<FiltersProvider>()) { Get.lazyPut<FiltersProvider>(() => FiltersProvider(), fenix: true); } if (!Get.isRegistered<CartProvider>()) { Get.lazyPut<CartProvider>(() => CartProvider(), fenix: true); } if (!Get.isRegistered<SearchProvider>()) { Get.lazyPut<SearchProvider>(() => SearchProvider(), fenix: true); } // 确认实例存在后再调用load if (Get.isRegistered<NotificationsProvider>()) { await Get.find<NotificationsProvider>().load(); } if (Get.isRegistered<FiltersProvider>()) { await Get.find<FiltersProvider>().load(); } if (Get.isRegistered<CartProvider>()) { await Get.find<CartProvider>().load(); } } catch (e) { print(e); } }
4. 检查应用启动流程中的重复执行点
在main函数开头添加日志,确认是否被多次执行:
Future<void> main() async { print("Main function executed"); // ... 其他代码 }
关键注意点
fenix: true会在实例销毁后重新创建,如果Provider是全局持久的,可考虑去掉该参数或改用permanent: true。- 异步操作中避免多次调用
Get.find,确保实例初始化完成后再执行后续逻辑。 - 对比正常运行的另一款应用,检查GetX、Firebase等依赖包的版本是否一致,版本差异可能导致该问题。
内容的提问来源于stack exchange,提问作者Mocha
相关产品推荐
相关产品推荐

