使用GetX时RxMap列表仅热重载后更新,Obx不自动刷新求助
Flutter GetX RxMap 不刷新 UI 问题排查与解决
问题根源
GetX 的 RxMap 仅监听顶层键值对的新增/删除/替换,如果 Map 中存储的是普通 List,修改 List 内部元素(如 add)不会触发 RxMap 的更新通知,导致 Obx 组件无法感知数据变化,只有热重载时才会刷新。
另外,ctrl.applicantDocuments.value[i] 报错是因为 value 是 RxMap 的受保护成员,外部不能直接访问,正确方式是通过 [] 操作符访问 Map 元素。
解决方案
方案1:将内部 List 改为 RxList
把 RxMap 的值类型换成 RxList,让每个 List 本身也具备可观察性,修改 List 时自动触发 UI 更新:
修改后的控制器代码
class MyAppliesController extends GetxController { // 将 List 改为 RxList RxMap<int, RxList<NewDocumentsRequest>> applicantDocuments = <int, RxList<NewDocumentsRequest>>{}.obs; void addDocumentToList( int applicantId, NewDocumentsRequest document, VisaModel visaModel) { if (!applicantDocuments.containsKey(applicantId)) { // 初始化时创建 RxList applicantDocuments[applicantId] = <NewDocumentsRequest>[].obs; } bool documentExists = applicantDocuments[applicantId]!.any( (existingDocument) => existingDocument.documentType == document.documentType); if (!documentExists) { if (applicantDocuments[applicantId]!.length < visaModel.visaApplicants![applicantId].visaDocuments!.length) { // 直接调用 RxList 的 add 即可触发更新 applicantDocuments[applicantId]!.add(document); } else { print('Applicant already has 3 documents'); } } else { errorSnackBar('alreadyDownload'); errorSnackBar('alreadyDownload'); } } }
方案2:修改 List 后手动触发 RxMap 更新
如果不想修改 List 类型,可以在修改 List 后,通过重新赋值或调用 refresh() 强制触发 RxMap 的更新通知:
修改后的控制器代码(addDocumentToList 方法)
void addDocumentToList( int applicantId, NewDocumentsRequest document, VisaModel visaModel) { if (!applicantDocuments.containsKey(applicantId)) { applicantDocuments[applicantId] = []; } bool documentExists = applicantDocuments[applicantId]!.any( (existingDocument) => existingDocument.documentType == document.documentType); if (!documentExists) { if (applicantDocuments[applicantId]!.length < visaModel.visaApplicants![applicantId].visaDocuments!.length) { final currentList = applicantDocuments[applicantId]!; currentList.add(document); // 重新赋值触发 RxMap 更新 applicantDocuments[applicantId] = currentList; // 或者调用 refresh() 强制通知 // applicantDocuments.refresh(); } else { print('Applicant already has 3 documents'); } } else { errorSnackBar('alreadyDownload'); errorSnackBar('alreadyDownload'); } }
修正 UI 代码
- 将空判断移到
Obx内部,确保响应式更新 - 移除错误的
.value访问方式,直接通过[]获取元素
修改后的界面代码
Obx(() { final documents = ctrl.applicantDocuments[i]; // 空判断放到 Obx 内部 if (documents == null || documents.isEmpty) { return const SizedBox(); } return ListView.builder( physics: const ScrollPhysics(), shrinkWrap: true, itemCount: documents.length, itemBuilder: (ctx, index) { return DownloadDocTile( title: documents[index].documentTypeName.toString() ?? '', trailing: Icon( FontAwesomeIcons.circleQuestion, color: AppColors.neutral700, ), ); }); })
内容的提问来源于stack exchange,提问作者Bear
相关产品推荐
相关产品推荐

