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

Flutter Get CLI项目中onInit函数失效问题求助

Controller的onInit无法执行的成因及解决方法

问题描述

用Get CLI创建Flutter应用后,发现Controller中的onInit函数无法正常执行,只有在View中用GetBuilder包裹并手动初始化Controller才能解决,但应用内页面过多,无法逐个修改,询问问题成因。

相关代码

Binding代码

import 'package:get/get.dart';
import '../controllers/login_controller.dart';

class LoginBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut<LoginController>(
      () => LoginController(),
    );
  }
}

Controller代码

import 'package:get/get.dart';

class LoginController extends GetxController {
  final count = 0.obs;
  
  @override
  void onInit() {
    print('but i work fine');
    super.onInit();
  }

  @override
  void onReady() {
    super.onReady();
  }

  @override
  void onClose() {
    super.onClose();
  }

  void increment() => count.value++;
}

原View代码(onInit失效)

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../routes/app_pages.dart';
import '../controllers/login_controller.dart';

class LoginView extends GetView<LoginController> {
  const LoginView({Key? key}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Center(
          child: SingleChildScrollView(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'EVIDENCIA',
                  style: TextStyle(
                    fontSize: 32,
                    fontWeight: FontWeight.bold,
                    color: Colors.blue,
                  ),
                ),
                SizedBox(height: 8),
                Text(
                  'Evidence based history taking',
                  style: TextStyle(
                    fontSize: 18,
                    color: Colors.black54,
                  ),
                ),
                SizedBox(height: 16),
                Text(
                  'be with us',
                  style: TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    color: Colors.black87,
                  ),
                ),
                SizedBox(height: 32),
                TextField(
                  decoration: InputDecoration(
                    labelText: 'Username',
                    border: OutlineInputBorder(),
                  ),
                ),
                SizedBox(height: 16),
                TextField(
                  decoration: InputDecoration(
                    labelText: 'Password',
                    border: OutlineInputBorder(),
                  ),
                  obscureText: true,
                ),
                SizedBox(height: 24),
                ElevatedButton(
                  onPressed: () {},
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.blue,
                    minimumSize: Size(double.infinity, 50),
                  ),
                  child: Text('login'),
                ),
                SizedBox(height: 24),
                Text(
                  'evidencia.com',
                  style: TextStyle(
                    fontSize: 16,
                    color: Colors.black54,
                  ),
                ),
                SizedBox(height: 16),
                GestureDetector(
                  onTap: () {
                    Get.offAndToNamed(Routes.REGISTER);
                  },
                  child: Text(
                    'register',
                    style: TextStyle(
                      fontSize: 16,
                      color: Colors.blue,
                      decoration: TextDecoration.underline,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

修复后的View代码(onInit生效)

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../routes/app_pages.dart';
import '../controllers/login_controller.dart';

class LoginView extends GetView<LoginController> {
  const LoginView({Key? key}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return GetBuilder<LoginController>(
        init: LoginController(),
        builder: (controller) {
          return Scaffold(
            resizeToAvoidBottomInset: false,
            body: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Center(
                child: SingleChildScrollView(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(
                        'EVIDENCIA',
                        style: TextStyle(
                          fontSize: 32,
                          fontWeight: FontWeight.bold,
                          color: Colors.blue,
                        ),
                      ),
                      SizedBox(height: 8),
                      Text(
                        'Evidence based history taking',
                        style: TextStyle(
                          fontSize: 18,
                          color: Colors.black54,
                        ),
                      ),
                      SizedBox(height: 16),
                      Text(
                        'be with us',
                        style: TextStyle(
                          fontSize: 20,
                          fontWeight: FontWeight.bold,
                          color: Colors.black87,
                        ),
                      ),
                      SizedBox(height: 32),
                      TextField(
                        decoration: InputDecoration(
                          labelText: 'Username',
                          border: OutlineInputBorder(),
                        ),
                      ),
                      SizedBox(height: 16),
                      TextField(
                        decoration: InputDecoration(
                          labelText: 'Password',
                          border: OutlineInputBorder(),
                        ),
                        obscureText: true,
                      ),
                      SizedBox(height: 24),
                      ElevatedButton(
                        onPressed: () {},
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.blue,
                          minimumSize: Size(double.infinity, 50),
                        ),
                        child: Text('login'),
                      ),
                      SizedBox(height: 24),
                      Text(
                        'evidencia.com',
                        style: TextStyle(
                          fontSize: 16,
                          color: Colors.black54,
                        ),
                      ),
                      SizedBox(height: 16),
                      GestureDetector(
                        onTap: () {
                          Get.offAndToNamed(Routes.REGISTER);
                        },
                        child: Text(
                          'register',
                          style: TextStyle(
                            fontSize: 16,
                            color: Colors.blue,
                            decoration: TextDecoration.underline,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          );
        });
  }
}

问题成因

  1. 懒加载触发条件未满足:Binding中使用Get.lazyPut注册Controller,这是懒加载模式——只有当Controller被首次访问(比如调用其属性、方法,或通过Get.find()、状态控件获取)时,才会实例化Controller并执行onInit。
  2. GetView未触发实例化:原View继承GetView<LoginController>,仅提供了controller getter,但整个View的build方法中没有任何地方实际访问这个controller(没有用它的变量、方法,也没有绑定状态控件),所以Get.lazyPut的实例化条件未触发,Controller从未被创建,onInit自然不会执行。
  3. GetBuilder手动初始化的作用:使用GetBuilder并传入init: LoginController()时,会手动创建Controller实例,此时onInit会被执行,但这种方式会创建新的Controller实例,和Binding中注册的不是同一个,属于临时解决方法,存在实例不一致的隐患。

无需逐个修改页面的解决方法

  • 方案1:主动触发懒加载:在View的build方法开头添加一行final _ = controller;,主动访问Controller,触发Get.lazyPut的实例化逻辑,无需修改页面结构。
  • 方案2:改用立即初始化:将Binding中的Get.lazyPut改为Get.put,这样路由跳转时Binding执行后会立即实例化Controller,直接触发onInit,不需要等待访问。注意Get.put是立即初始化,适合需要提前执行初始化逻辑的场景。
  • 方案3:检查路由绑定:确认AppPages中对应路由是否正确绑定了LoginBinding,确保路由跳转时Binding被执行,Controller被正确注册。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 12:51:00