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

Flutter GetX中Map/List内数据更新后Widget不刷新问题求助

Flutter GetX中RxList/RxMap内模型属性更新不触发UI刷新问题解决

问题场景

使用Flutter GetX框架开发时,控制器中定义了RxMap<int, ProductModel>、RxList<ProductModel>和RxInt类型变量:

  • RxInt类型的count变量更新时,UI能正常通过Obx刷新
  • 修改RxList或RxMap中ProductModel的piece属性后,Obx包裹的Widget无法自动刷新

相关代码

控制器代码

class Controller extends GetxController {
  RxMap<int, ProductModel> purchaseListe = <int, ProductModel>{}.obs; 
  RxList<ProductModel> foundedItem = <ProductModel>[].obs; // 已初始化包含产品数据
  var count = 0.obs; // 能正常触发UI刷新的变量

  void add(int index, bool isAdded) {
    if (isAdded) {
      foundedItem[index].piece++;
      print("点击的元素索引 = $index");
      count++;
      if (foundedItem[index].piece == 1) {
        purchaseListe.addAll({index: foundedItem[index]});
      }
    } else {
      foundedItem[index].piece--;
      print("点击的元素索引 = $index");
      count--;
      if (foundedItem[index].piece == 0) {
        purchaseListe.remove(index);
      }
    }
    update();
  }
}

UI代码

Container(
  height: 25,
  width: 25.0,
  child: Obx(
    () {
      return Text(
        widgetController.foundedItem[widget.itemIndex].piece.toString(),
      );
    },
  ),
)

模型代码

class ProductModel {
  String productCode;
  String productName;
  var productPrice;
  var productSalePrice;
  var productScore;
  String productImageUrl;
  int piece;

  ProductModel({
    required this.productCode,
    required this.productName,
    this.productPrice,
    this.productSalePrice,
    this.productScore,
    required this.productImageUrl,
    required this.piece,
  });
}

问题原因

GetX的RxList/RxMap这类响应式集合,仅会监听集合本身的引用变化(比如添加/删除元素、替换整个集合对象),但不会监听集合内部元素的属性变化。
你的ProductModel是普通类,piece是普通int类型,修改piece属于对象内部状态变更,RxList无法感知到这种变化,因此Obx不会触发UI刷新。

而count是RxInt类型,本身就是响应式变量,修改count.value(或直接count++)会直接触发监听,所以UI能正常刷新。

解决方法

方法一:将模型属性改为响应式类型

把ProductModel中的piece改为RxInt,让单个属性具备响应式能力,这样修改属性时Obx能直接监听变化:

修改后的模型代码

class ProductModel {
  String productCode;
  String productName;
  var productPrice;
  var productSalePrice;
  var productScore;
  String productImageUrl;
  RxInt piece; // 改为RxInt响应式类型

  ProductModel({
    required this.productCode,
    required this.productName,
    this.productPrice,
    this.productSalePrice,
    this.productScore,
    required this.productImageUrl,
    required int piece, // 构造函数仍接收int类型
  }) : piece = piece.obs; // 初始化转为RxInt
}

修改后的UI代码(获取值需用.value)

Container(
  height: 25,
  width: 25.0,
  child: Obx(
    () {
      return Text(
        widgetController.foundedItem[widget.itemIndex].piece.value.toString(),
      );
    },
  ),
)

控制器中修改属性的方式不变,foundedItem[index].piece++ 可正常使用(RxInt重载了运算符)。


方法二:更新集合元素的引用

修改piece后,将整个ProductModel对象重新赋值给集合对应的位置,让RxList感知到元素引用变化:

修改后的控制器add方法

void add(int index, bool isAdded) {
  // 先取出当前元素
  final product = foundedItem[index];
  if (isAdded) {
    // 修改属性后,创建新的对象
    final updatedProduct = ProductModel(
      productCode: product.productCode,
      productName: product.productName,
      productPrice: product.productPrice,
      productSalePrice: product.productSalePrice,
      productScore: product.productScore,
      productImageUrl: product.productImageUrl,
      piece: product.piece + 1, // 更新piece
    );
    foundedItem[index] = updatedProduct; // 重新赋值,触发RxList监听
    print("点击的元素索引 = $index");
    count++;
    if (updatedProduct.piece == 1) {
      purchaseListe.addAll({index: updatedProduct});
    }
  } else {
    final updatedProduct = ProductModel(
      productCode: product.productCode,
      productName: product.productName,
      productPrice: product.productPrice,
      productSalePrice: product.productSalePrice,
      productScore: product.productScore,
      productImageUrl: product.productImageUrl,
      piece: product.piece - 1, // 更新piece
    );
    foundedItem[index] = updatedProduct; // 重新赋值
    print("点击的元素索引 = $index");
    count--;
    if (updatedProduct.piece == 0) {
      purchaseListe.remove(index);
    }
  }
  // 此处update()可删除,Obx依赖Rx变量监听,update()是GetBuilder的刷新机制
  // update();
}

这种方式无需修改模型和UI代码,适合不想改动模型结构的场景。

额外提示

控制器中的update()方法是用于GetBuilder的刷新机制,当前使用Obx依赖Rx变量监听,可去掉update()避免不必要的性能消耗。

内容的提问来源于stack exchange,提问作者Bora Tan Demir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 13:36:39