You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 21:45:28