GetXBuilder与ListViewBuilder联动失效:TextField值不更新UI问题
Flutter GetX批量更新TextField值后UI未同步的解决方案
问题场景
开发Flutter App时,需求是点击按钮批量为所有TextField设置值。采用GetX框架实现逻辑后,数据已在List中更新,但用户界面(UI)未同步显示更新后的值。
现有代码片段
页面核心代码(GetBuilder+ListViewBuilder)
GetBuilder<LabourBulkController>(builder: (dx) { return ListView.builder( itemCount: dx.workersList.length, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (BuildContext context, int index) { return Card( child: Padding( padding: const EdgeInsets.all(8.0), child: Column(children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.start, children: [ const SizedBox( width: 10, height: 50, ), const Icon(FeatherIcons.user), const SizedBox( width: 20, ), Text( "${dx.workersList[index]['name']}", style: const TextStyle(fontSize: 18), ), ], ), TextFormField( keyboardType: TextInputType.number, decoration: const InputDecoration( border: OutlineInputBorder(), hintText: "Wages", prefixIcon: Icon( Icons.wallet, color: Colors.blue, )), initialValue: dx.workersList[index]['amount'].toString(), onChanged: (value) { _bulkController.workersList[index]['amount'] = value; }, ) ]), ), ); }); }),
浮动按钮代码
FloatingActionButton( onPressed: () async { print(_bulkController.workersList); }, child: const Icon(Icons.cloud_upload)),
Controller代码
import 'dart:convert'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; class LabourBulkController extends GetxController { RxList workersList = [].obs; RxBool loading = false.obs; getActiveLabours() async { loading.value = true; SharedPreferences prefs = await SharedPreferences.getInstance(); var token = prefs.getString("token"); var response = await http.get( Uri.parse("http://10.0.2.2:8000/api/supervisor/active/labours"), headers: { 'Authorization': 'Bearer $token', }); var data = jsonDecode(response.body); workersList.clear(); for (var i = 0; i < data['data'].length; i++) { Map customerData = { "id": data['data'][i]['worker_id'], "name": data['data'][i]['worker_name'], "amount": 0, }; workersList.add(customerData); } loading.value = false; update(); } assignAtOnce(String amount) { loading.value = true; for (var i = 0; i < workersList.length; i++) { workersList[i]['amount'] = amount; loading.value = false; } update(); } }
问题原因
- TextFormField的initialValue特性:
initialValue仅在组件第一次构建时生效,后续数据更新不会自动触发TextField刷新。 - 缺少实时数据绑定:TextField未与响应式控制器关联,仅依赖列表数据的初始值,无法感知数据变化。
- RxList内部Map变化检测限制:RxList仅监听列表的增删操作,内部普通Map的属性变化无法自动触发UI更新(核心问题还是TextField的初始化方式)。
解决方案
通过为每个TextField绑定TextEditingController,实现文本的实时更新与UI同步,具体步骤如下:
1. 修改Controller,添加控制器列表
在LabourBulkController中添加TextEditingController列表,用于管理每个TextField的文本,并在获取数据时初始化控制器:
import 'dart:convert'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; class LabourBulkController extends GetxController { RxList workersList = [].obs; RxBool loading = false.obs; // 添加控制器列表 List<TextEditingController> amountControllers = []; getActiveLabours() async { loading.value = true; SharedPreferences prefs = await SharedPreferences.getInstance(); var token = prefs.getString("token"); var response = await http.get( Uri.parse("http://10.0.2.2:8000/api/supervisor/active/labours"), headers: { 'Authorization': 'Bearer $token', }); var data = jsonDecode(response.body); workersList.clear(); amountControllers.clear(); // 清空旧控制器 for (var i = 0; i < data['data'].length; i++) { Map customerData = { "id": data['data'][i]['worker_id'], "name": data['data'][i]['worker_name'], "amount": 0, }; workersList.add(customerData); // 初始化控制器,设置初始值 amountControllers.add(TextEditingController(text: "0")); } loading.value = false; update(); } assignAtOnce(String amount) { loading.value = true; for (var i = 0; i < workersList.length; i++) { workersList[i]['amount'] = amount; // 更新对应控制器的文本 amountControllers[i].text = amount; } loading.value = false; update(); } // 页面销毁时释放控制器,防止内存泄漏 @override void onClose() { for (var controller in amountControllers) { controller.dispose(); } super.onClose(); } }
2. 修改页面TextField,绑定控制器
去掉initialValue,改为绑定Controller中的amountControllers:
TextFormField( controller: dx.amountControllers[index], keyboardType: TextInputType.number, decoration: const InputDecoration( border: OutlineInputBorder(), hintText: "Wages", prefixIcon: Icon( Icons.wallet, color: Colors.blue, )), onChanged: (value) { _bulkController.workersList[index]['amount'] = value; }, )
3. 修改浮动按钮,调用批量更新方法
添加金额输入对话框,调用assignAtOnce方法完成批量更新:
FloatingActionButton( onPressed: () async { // 弹出输入对话框获取金额 final TextEditingController inputController = TextEditingController(); bool? confirm = await Get.dialog( AlertDialog( title: const Text('批量设置工资'), content: TextField( controller: inputController, keyboardType: TextInputType.number, decoration: const InputDecoration(hintText: '输入金额'), ), actions: [ TextButton( onPressed: () => Get.back(result: false), child: const Text('取消'), ), TextButton( onPressed: () => Get.back(result: true), child: const Text('确定'), ), ], ), ); if (confirm == true && inputController.text.isNotEmpty) { _bulkController.assignAtOnce(inputController.text); } }, child: const Icon(Icons.cloud_upload)),
效果说明
修改后,点击浮动按钮输入金额并确认,所有TextField的文本会立即同步更新,同时workersList中的数据也会保持一致,实现数据与UI的双向同步。
内容的提问来源于stack exchange,提问作者swapnil mane
相关产品推荐
相关产品推荐

