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
相关产品推荐
相关产品推荐

