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

LayoutBuilder致GetX实例重启丢数据,如何保留Controller实例?

解决Flutter Web中GetX Controller因屏幕尺寸变化丢失数据的问题

问题核心原因

你当前的代码存在两个关键问题导致Controller实例被意外销毁重建:

  1. 在_MainState的成员变量中直接执行Get.put(),若因窗口尺寸变化触发组件树重构(Web端部分场景下可能发生),会重复执行初始化逻辑;
  2. 使用普通MaterialApp而非GetX提供的GetMaterialApp,无法保障Controller的生命周期与应用全局状态绑定。

具体解决方案

方案一:改用GetMaterialApp并规范Controller初始化

这是最稳妥的方案,利用GetX官方集成的应用组件来管理Controller生命周期:

class _MainState extends State<Main>{
  late Controller controller;

  @override
  void initState() {
    super.initState();
    // 仅在首次初始化时创建实例,已存在则直接返回已有实例
    controller = Get.put(Controller(), permanent: true);
  }

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
        debugShowCheckedModeBanner: false,
        home: Container(
          width: largura_total,
          height: altura_total,
          decoration: BoxDecoration(
              color: Colors.white,
              image: DecorationImage(
                  image: AssetImage('assets/wallpaper-tela.jpg'),
                  fit: BoxFit.cover
              )
          ),
          child: LayoutBuilder(
              builder: (context, constraints){
                var largura = constraints.maxWidth;
                var altura = constraints.maxHeight;
                var largura_coluna = (largura - 240)/14;
                if(largura>1400 && altura > 500){
                  return Scaffold([...]);
                }
                else if(largura>1000 && largura<1400 && altura > 500){
                  return Scaffold([...]);
                }
                else if(largura<1000 && largura>350 && altura > 500){
                  return Scaffold([...]);
                } else {
                  return Scaffold([...]);
                }
              }
          ),
        )
    );
  }
}

方案二:用Get.find()复用已存在的Controller实例

如果不想替换MaterialApp,可以通过判断实例是否已注册来避免重复初始化:

class _MainState extends State<Main>{
  Controller get controller => Get.find<Controller>();

  @override
  void initState() {
    super.initState();
    // 仅在实例未注册时初始化
    if (!Get.isRegistered<Controller>()) {
      Get.put(Controller(), permanent: true);
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        // 原有代码保持不变
        home: Container(
          child: LayoutBuilder(
              builder: (context, constraints){
                // 使用controller时直接调用this.controller即可
                // 原有布局逻辑不变
              }
          ),
        )
    );
  }
}

调试排查辅助

如果仍出现Controller销毁的情况,可以在Controller中添加日志确认销毁触发点:

class Controller extends GetxController{
    var lista_mostrar = <ItemMostrar>[].obs;

    @override
    void onClose() {
      print("Controller被销毁"); // 控制台输出调试信息
      super.onClose();
    }
}

若打印该日志,说明有代码主动调用了Get.delete<Controller>()或类似销毁方法,需排查业务逻辑中的相关代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 00:32:30