如何在构造函数中保存异步方法返回的Map<String, dynamic>?
问题分析
你的核心问题在于构造函数是同步执行的,而readJson()是异步方法,then回调里的赋值操作会在构造函数执行完毕后才触发。这会导致两个问题:
- 构造函数里的日志打印的始终是初始的空
Map - 外部代码使用
TestRemoteConfigManager实例时,testValues可能还未完成赋值
下面提供三种可行的解决方案,你可以根据场景选择:
方案一:异步工厂构造函数(推荐)
通过异步工厂构造函数,确保实例创建完成时testValues已经被正确初始化,从根源避免异步同步冲突:
class TestRemoteConfigManager { Map<String, dynamic> testValues = {}; // 私有构造函数,禁止直接实例化 TestRemoteConfigManager._(); // 异步工厂方法,返回初始化完成的实例 static Future<TestRemoteConfigManager> create() async { final instance = TestRemoteConfigManager._(); instance.testValues = await instance.readJson(); SLogger.i('testValues from factory constructor-->${instance.testValues}'); return instance; } Future<Map<String, dynamic>> readJson() async { final Map<String, dynamic> data = await json.decode( await rootBundle.loadString('assets/uat/remote_config_defaults.json')); SLogger.i('read data: $data'); return data; } }
使用方式:
// 必须用await获取实例,确保初始化完成 final configManager = await TestRemoteConfigManager.create();
方案二:单独初始化方法
保持原构造函数不变,新增一个异步初始化方法,创建实例后手动调用并等待完成:
class TestRemoteConfigManager { Map<String, dynamic> testValues = {}; TestRemoteConfigManager(); // 异步初始化方法 Future<void> init() async { testValues = await readJson(); SLogger.i('testValues after init-->${testValues}'); } Future<Map<String, dynamic>> readJson() async { final Map<String, dynamic> data = await json.decode( await rootBundle.loadString('assets/uat/remote_config_defaults.json')); SLogger.i('read data: $data'); return data; } }
使用方式:
final configManager = TestRemoteConfigManager(); // 等待初始化完成后再使用 await configManager.init();
方案三:late延迟初始化
用late修饰testValues,延迟初始化,但要注意必须确保初始化完成后再访问该属性,否则会抛出LateInitializationError:
class TestRemoteConfigManager { // late修饰,延迟赋值 late Map<String, dynamic> testValues; TestRemoteConfigManager() { _init(); } // 私有异步初始化方法 Future<void> _init() async { testValues = await readJson(); SLogger.i('testValues after init-->${testValues}'); } Future<Map<String, dynamic>> readJson() async { final Map<String, dynamic> data = await json.decode( await rootBundle.loadString('assets/uat/remote_config_defaults.json')); SLogger.i('read data: $data'); return data; } }
注意事项:
- 适合能严格控制使用时机的场景(比如在页面
initState里等待_init完成,或用FutureBuilder监听初始化状态) - 禁止在
_init完成前访问testValues
内容的提问来源于stack exchange,提问作者Jagadeesh
相关产品推荐
相关产品推荐

