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

打开同一SearchPage实例后出现TextEditingController已释放报错求助

问题:TextEditingController已释放后仍被调用的错误

我有一个名为SearchPage()的页面,控制器代码如下:

class SearchPageController extends GetxController {
   final searchTextController = TextEditingController();
   
   @override
   void onInit() {
     super.onInit();
   }

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

SearchPage页面代码如下:

class SearchPage extends StatelessWidget {
  const SearchPage({super.key});

  @override
  Widget build(BuildContext context) {
      final controller = Get.put(SearchPageController());

      return aWidgetHere();
  }
}

该页面包含TextField、Button等组件,点击按钮时执行以下代码打开内容不同但保留TextField的同一SearchPage:

Get.off(() => const SearchPage(), arguments: [arguments], preventDuplicates: false);

但点击TextField时出现报错:A TextEditingController was used after being disposed. Once you have called dispose() on a TextEditingController, it can no longer be used.

明明页面已重新初始化,为何会出现该错误?


原因分析

问题核心在于GetX的控制器复用机制和页面跳转逻辑的冲突:

  1. 调用Get.off()时,旧的SearchPage会被销毁,绑定的SearchPageController会触发onClose(),导致内部的searchTextController被释放。
  2. Get.put(SearchPageController())默认会复用同类型的已存在控制器实例(未指定唯一标识时)。新页面创建时,Get.put()返回的还是那个已经执行过dispose()的旧控制器,其内部的searchTextController已失效,因此点击TextField会触发错误。

解决方案

提供两种有效解决方式:

方式一:用唯一Tag区分控制器实例

创建控制器时指定唯一Tag,确保新页面生成全新的控制器实例:

// 页面中创建控制器时添加唯一Tag
final controller = Get.put(SearchPageController(), tag: UniqueKey().toString());

// 控制器onClose中可主动移除对应Tag的实例
@override
void onClose(){
  searchTextController.dispose();
  Get.delete<SearchPageController>(tag: tag);
  super.dispose();
}

方式二:用Get.create()替代Get.put()

Get.create()每次都会生成新的控制器实例,不会复用旧实例:

// 页面中替换Get.put为Get.create
final controller = Get.create(() => SearchPageController());

额外优化:保留TextField输入内容

如果需要保留跳转前的输入内容,可在跳转时传递参数,新页面初始化时赋值:

// 跳转前获取当前输入值
final searchContent = controller.searchTextController.text;
// 跳转时传入参数
Get.off(() => const SearchPage(), arguments: searchContent, preventDuplicates: false);

// 控制器onInit中初始化内容
@override
void onInit() {
  super.onInit();
  final savedContent = Get.arguments as String?;
  if(savedContent != null){
    searchTextController.text = savedContent;
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 11:03:12