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

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();
  }
}

问题原因

  1. TextFormField的initialValue特性:initialValue仅在组件第一次构建时生效,后续数据更新不会自动触发TextField刷新。
  2. 缺少实时数据绑定:TextField未与响应式控制器关联,仅依赖列表数据的初始值,无法感知数据变化。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 00:25:19