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

Flutter GetX中GetxController的onReady为何在onInit后延迟?

GetX中onInit与onReady执行间隔过长的原因与解决办法

问题场景

我正在使用Flutter结合GetX框架开发,编写了如下TimerController:

class TimerController extends GetxController {
  int secondsRemaining = 5;

  late Timer timer;
  void startTimer() {
    timer = Timer.periodic(Duration(seconds: 1), (Timer t) {
      update();
    });
  }

  @override
  void onInit() {
    print('${DateTime.now()}');
    print("onInit");
    super.onInit();
  }

  @override
  void onReady() {
    print("onReady");
    print('${DateTime.now()}');
    super.onReady();
  }
}

并在页面中按如下方式使用该控制器:

class _PageState extends State<Page> {
  TimerController timerController =
      Get.put(TimerController());

 @override
  Widget build(BuildContext context) {
  return GetBuilder<TimerController>(
            initState: (data) => timerController.startTimer(),
            dispose: (_) => timerController.stopTimer(),
            builder: (controller) {
              return Text('${timerController.secondsRemaining}s');
            },
          )
  }
}

路由跳转后,日志显示onInit与onReady的执行间隔约2秒:

[GETX] GOING TO ROUTE /Page
[GETX] Instance "TimerController" has been created
I/flutter ( 6948): 2023-11-21 17:53:54.057766
I/flutter ( 6948): onInit
[GETX] Instance "TimerController" has been initialized
I/flutter ( 6948): onReady
I/flutter ( 6948): 2023-11-21 17:53:56.379983

即使注释掉Timer相关代码,延迟问题依然存在。请问该问题产生的原因是什么,如何解决?


原因分析

问题核心在于控制器初始化时机过早:你在State的成员变量中直接调用Get.put(TimerController()),这会让控制器在State创建阶段就完成初始化(触发onInit),但此时页面的Widget树尚未构建完成。直到build方法执行并渲染GetBuilder组件时,GetX才会触发控制器的onReady方法,两者的时间差就是页面Widget构建、渲染的耗时,因此出现了2秒左右的间隔。

这种写法还会导致控制器生命周期与页面State不同步,可能引发不必要的性能损耗或内存泄漏风险。

解决办法

1. 让GetBuilder统一管理控制器初始化

将控制器的初始化移到GetBuilder的init参数中,由GetX管控控制器的生命周期,确保onInit和onReady的执行时机更贴合:

class _PageState extends State<Page> {
  @override
  Widget build(BuildContext context) {
    return GetBuilder<TimerController>(
      init: TimerController(), // 在此处初始化控制器
      initState: (data) => data.startTimer(),
      dispose: (_) => _.stopTimer(),
      builder: (controller) {
        return Text('${controller.secondsRemaining}s');
      },
    );
  }
}

2. 延迟获取控制器(适用于需要在State中调用控制器方法的场景)

如果必须在State中持有控制器实例,不要在成员变量中直接初始化,而是在initState方法中完成控制器的获取,确保页面初始化后再创建控制器:

class _PageState extends State<Page> {
  late TimerController timerController;

  @override
  void initState() {
    super.initState();
    // 页面初始化阶段完成控制器注入
    timerController = Get.put(TimerController());
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<TimerController>(
      initState: (data) => timerController.startTimer(),
      dispose: (_) => timerController.stopTimer(),
      builder: (controller) {
        return Text('${controller.secondsRemaining}s');
      },
    );
  }
}

3. 完善控制器的生命周期方法(避免内存泄漏)

你的控制器缺少stopTimer方法,且未在onClose中处理定时器,补充后可避免内存泄漏:

class TimerController extends GetxController {
  int secondsRemaining = 5;
  late Timer timer;

  void startTimer() {
    timer = Timer.periodic(const Duration(seconds: 1), (Timer t) {
      if (secondsRemaining > 0) {
        secondsRemaining--;
        update();
      } else {
        timer.cancel();
      }
    });
  }

  void stopTimer() {
    timer.cancel(); // 取消定时器
  }

  @override
  void onInit() {
    print('${DateTime.now()}');
    print("onInit");
    super.onInit();
  }

  @override
  void onReady() {
    print("onReady");
    print('${DateTime.now()}');
    super.onReady();
  }

  @override
  void onClose() {
    stopTimer(); // 控制器销毁时自动清理定时器
    super.onClose();
  }
}

通过以上修改,控制器的onInit与onReady执行间隔会大幅缩短,同时能保证控制器生命周期与页面同步,避免潜在的内存泄漏问题。


内容的提问来源于stack exchange,提问作者magic_9527

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 16:23:26