Flutter GetX实现控制器顺序初始化 避免onInit重复调用
解决GetX中控制器异步初始化顺序问题(确保Controller1仅初始化一次)
你当前的问题出在Controller2的onInit中手动调用了controller1.onInit()——GetX在执行Get.put(Controller1())时已经自动触发了一次onInit,手动调用会导致重复执行。以下是两种可行的解决方案:
方案一:在Controller1中添加初始化完成标记,Controller2等待该标记
这种方案将初始化完成的信号封装在Controller1内部,通过Future传递状态,保持控制器逻辑的内聚性。
修改Controller1
添加Completer来标记初始化完成,对外暴露对应的Future:
class Controller1 extends GetxController { var dataToShare = ''.obs; final _initCompleter = Completer<void>(); // 对外提供初始化完成的Future Future get initComplete => _initCompleter.future; @override Future<void> onInit() async { super.onInit(); // 执行异步初始化操作 dataToShare.value = await fetchData(); // 标记初始化完成 _initCompleter.complete(); } // 模拟异步数据获取逻辑 Future<String> fetchData() async { await Future.delayed(const Duration(seconds: 2)); return "Controller1加载的数据"; } }
修改Controller2
不再手动调用Controller1的onInit,而是等待其initComplete Future完成后再执行自身逻辑:
class Controller2 extends GetxController { final String uniqueId; Controller2({required this.uniqueId}); @override Future<void> onInit() async { super.onInit(); // 获取已通过Get.put初始化的Controller1实例 final controller1 = Get.find<Controller1>(tag: uniqueId); // 等待Controller1初始化完成 await controller1.initComplete; // 安全获取共享数据并处理 final fetchedData = controller1.dataToShare.value; processData(fetchedData); } void processData(String data) { print("Controller2处理数据:$data"); } }
Widget代码保持不变
Widget中先put Controller1再put Controller2的顺序无需修改,Controller2的onInit会自动等待Controller1完成:
class MyWidget extends StatelessWidget { @override Widget build(BuildContext context) { final uniqueId = '123'; final Controller1 controller1 = Get.put( Controller1(), tag: uniqueId, ); final Controller2 controller2 = Get.put( Controller2(uniqueId: uniqueId), tag: uniqueId, ); return Container( child: const Text("应用内容"), ); } }
方案二:在Widget中等待Controller1初始化完成后再初始化Controller2
如果希望Controller2完全在Controller1初始化完成后才被实例化,可以使用FutureBuilder:
class MyWidget extends StatelessWidget { @override Widget build(BuildContext context) { final uniqueId = '123'; // 先初始化Controller1 final controller1 = Get.put(Controller1(), tag: uniqueId); return FutureBuilder( future: controller1.initComplete, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { // Controller1初始化完成后,再初始化Controller2 Get.put(Controller2(uniqueId: uniqueId), tag: uniqueId); return const Text("所有控制器初始化完成"); } else { // 显示加载状态 return const CircularProgressIndicator(); } }, ); } }
这种方案的优势是Controller2不会提前被实例化,只有在Controller1准备好后才会创建并执行其onInit。
内容的提问来源于stack exchange,提问作者user2181948
相关产品推荐
相关产品推荐

