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

Flutter中使用GetX Provider构造函数时值设置异常的问题

问题解析与解决方案

核心原因:Get.put()的执行逻辑

你遇到的现象本质是对GetX依赖注入机制的误解,具体拆解:

  1. 当你调用Get.put(AppProvider())时,首先会执行AppProvider()构造函数创建一个新实例,所以每次都会触发构造函数里的print(getNumbers.length),输出0;
  2. 接着GetX会检查内部的依赖容器,判断是否已经存在AppProvider类型的实例:
    • 第一次跳转时,容器为空,GetX会把刚创建的实例存入容器,后续返回的都是这个实例;
    • 第二次跳转时,容器里已经有了之前保存数据的实例,GetX会丢弃刚创建的新实例,直接返回容器中已有的旧实例;
  3. 你界面上使用的provider变量是容器里的旧实例,所以能看到之前添加的数字,但构造函数的打印来自被丢弃的新实例,所以显示0。

验证逻辑的方法

在AppProvider里添加实例哈希值打印,就能直观看到新旧实例的区别:

AppProvider() {
  _numbers = [];
  print("构造函数执行,实例hashCode: $hashCode,列表长度: ${getNumbers.length}");
}

void addNumber(int number) {
  _numbers.add(number);
  print("添加数据,当前实例hashCode: $hashCode,列表长度: ${getNumbers.length}");
  update();
}

第二次跳转时,你会看到构造函数打印的hashCode和后续操作实例的hashCode完全不同,证明是两个独立对象。

正确写法

方案1:提前全局初始化Provider

在App启动时(比如main函数)初始化一次,后续直接获取已有实例:

void main() {
  Get.put(AppProvider());
  runApp(MyApp());
}

然后在SecondScreen里直接获取:

final provider = Get.find<AppProvider>();

这样构造函数只会执行一次,不会产生多余的实例和打印。

方案2:用Get.find判断是否已存在实例

如果不想提前初始化,可以用Get.find配合Get.put,避免重复创建实例:

final provider = Get.find<AppProvider>() ?? Get.put(AppProvider());

额外优化点

  1. AppProvider里的_numbers已经在成员变量处初始化了[],不需要在构造函数里再次赋值;
  2. SecondScreen不需要用StatefulWidget,借助GetX的响应式能力,用Obx包裹刷新组件即可,无需手动调用setState():
class SecondScreen extends StatelessWidget {
  const SecondScreen({Key? key}) : super(key: key);
  final provider = Get.find<AppProvider>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Obx(() => Text(provider.getNumbers.length.toString(), style: const TextStyle(fontSize: 50))),
            TextButton(
              onPressed: () => Navigator.of(context).push(MaterialPageRoute(builder: (_) => const FirstScreen())),
              child: const Text('Move To First Screen'),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => provider.addNumber(Random().nextInt(1000)),
        child: const Icon(Icons.add),
      ),
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 23:43:26