Flutter中static final全局配置变量值偶发变动不稳定如何解决?
问题根因分析
- 你最初定义的
static final GlobalConfiguration config = GlobalConfiguration()确实只会在类加载时初始化一次,出现读取结果不稳定的核心原因是读取配置的时机和GlobalConfiguration配置加载完成的时机存在时序差:手动点击收藏时配置已经加载完成,所以读取成功;FM电台自动保存逻辑触发时间更早,此时配置还没写入到GlobalConfiguration的内部存储,就会读取失败。 - 你调整后的代码问题出在判断逻辑:你加了
if (globalConfig.appConfig.isNotEmpty)的判断,当初始化执行时如果GlobalConfiguration还没加载完配置,就不会给静态config赋值,后续读取自然拿到空值。
修复方案
我们可以通过强制初始化顺序、加状态校验的方式,实现配置要么全部加载完成对外提供服务,要么直接抛出异常,完全避免读取到不稳定的值,实现代码如下:
import 'package:global_configuration/global_configuration.dart'; import 'package:flutter/widgets.dart'; enum ConfigType { DEV, PRO } class GlobalConfig { // 私有构造函数,禁止外部实例化 GlobalConfig._(); // 不可修改的配置存储容器 static Map<String, String> _config = {}; // 配置初始化完成标记 static bool _initialized = false; // 统一初始化入口,必须在runApp之前调用完成 static Future<void> init(ConfigType configType) async { if (_initialized) return; // 等待配置文件加载完成,如果你是从其他渠道加载配置也要在这里await等待完成 await GlobalConfiguration().loadFromAsset("app_config"); final rawConfig = GlobalConfiguration().appConfig; // 校验必要配置项,缺少任意配置直接抛错,保证要么全成功要么全失败 final requiredKeys = ["baseUrl", "shareUrl", "staticUrl"]; for (var key in requiredKeys) { if (!rawConfig.containsKey(key) || rawConfig[key].toString().isEmpty) { throw Exception("配置加载失败,缺少必填项:$key"); } } // 锁死配置,后续不可修改 _config = Map.unmodifiable(rawConfig.cast<String, String>()); // 不同环境配置覆盖逻辑 switch (configType) { case ConfigType.DEV: // 开发环境特殊配置写这里 break; case ConfigType.PRO: // 生产环境特殊配置写这里 break; } _initialized = true; } // 所有读取方法统一校验初始化状态 static String getBaseUrl() { _checkInitState(); return _config["baseUrl"]!; } static String getShareUrl() { _checkInitState(); return _config["shareUrl"]!; } static String getStaticResourceUrl() { _checkInitState(); return _config["staticUrl"]!; } static String getConfig(String key) { _checkInitState(); return _config[key]!; } // 初始化状态校验,未初始化直接抛错,避免读到空值 static void _checkInitState() { if (!_initialized) { throw Exception("GlobalConfig未初始化,请先在main函数调用GlobalConfig.init完成加载"); } } }
使用注意事项
必须在main函数中runApp执行之前等待初始化完成,保证所有业务逻辑启动时配置已经就绪:
void main() async { // 初始化Flutter框架 WidgetsFlutterBinding.ensureInitialized(); // 等待配置加载完成 await GlobalConfig.init(ConfigType.PRO); runApp(const MyApp()); }
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

