Flutter中用GetX与无状态组件按需生成TextField的问题排查
Flutter中GetX结合Stateless Widget按需生成TextField的问题修复
代码错误分析
当前点击「+」按钮无法添加新TextField的核心问题是状态监听范围错误:
- 仅用
Obx包裹了单个TextField,但ListView.builder的itemCount直接读取controller.textFieldControllerList.length,未被GetX的状态监听覆盖。当RxList添加新元素时,itemCount的变化不会触发UI重建,导致ListView无法渲染新的列表项。 - 额外问题:在StatelessWidget的成员变量中直接调用
Get.put()不是最佳实践,可能导致重复注入控制器。
正确实现方式
核心修改点
- 将
Obx的范围扩大到ListView.builder,确保列表的itemCount和列表项都能响应RxList的变化。 - 使用
Get.find()获取已注入的控制器,避免重复初始化。
修改后的屏幕文件代码
import 'package:flutter/material.dart'; import 'package:dynamic_lists/controllers/2_ListWithInputBoxGetxController.dart'; import 'package:get/get.dart'; class ListWithInputBoxGetx extends StatelessWidget { ListWithInputBoxGetx({Key? argKey, this.title}) : super(key: argKey); final String? title; // 使用Get.find()获取已注入的控制器 final ListWithInputBoxGetxController controller = Get.find(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(title!)), body: Padding( padding: const EdgeInsets.all(10), child: SingleChildScrollView( child: Column( children: <Widget>[ Container( height: 400, color: Colors.limeAccent, // 用Obx包裹整个ListView.builder,监听RxList的变化 child: Obx(() => ListView.builder( itemCount: controller.textFieldControllerList.length, prototypeItem: const TextField(), itemBuilder: ((context, index) { return TextField( controller: controller.getTextFieldController(index), ); }), )), ), const SizedBox(height: 10), ElevatedButton( onPressed: controller.addTextField, child: const Text("+"), ), const SizedBox(height: 10), ElevatedButton( onPressed: controller.submit, child: const Icon(Icons.sailing), ) ], ), ), ), ); } }
修改后的控制器文件代码
(控制器核心逻辑无问题,仅优化类型声明并补充内存清理逻辑)
import 'package:get/get.dart'; import 'package:flutter/material.dart'; class ListWithInputBoxGetxController extends GetxController { RxList<TextEditingController> textFieldControllerList = <TextEditingController>[].obs; // 为参数添加类型声明,增强代码健壮性 TextEditingController getTextFieldController(int argIndex) { return textFieldControllerList[argIndex]; } void addTextField() { textFieldControllerList.add(TextEditingController()); } void submit() { // 示例:获取所有输入框内容 final inputs = textFieldControllerList.map((ctrl) => ctrl.text).toList(); print("提交的输入内容:$inputs"); } // 页面销毁时清理控制器,避免内存泄漏 @override void onClose() { for (var ctrl in textFieldControllerList) { ctrl.dispose(); } textFieldControllerList.clear(); super.onClose(); } }
额外注意事项
- 确保在使用
Get.find()之前,控制器已被注入。可在应用启动时全局注入,或在父Widget中提前调用Get.put(ListWithInputBoxGetxController())。
内容的提问来源于stack exchange,提问作者Aquarius_Girl
相关产品推荐
相关产品推荐

