Flutter使用GetX开发时favorite icon收藏图标点击后不更新
问题根源
changeStatus方法仅修改了传入的布尔值形参(Dart为值传递),没有实际修改列表内对应条目的isfav属性,数据源根本没变化- 响应式变量
RxList搭配update()使用逻辑错误:update()是GetBuilder非响应式状态管理的刷新方法,对.obs声明的响应式变量无效 - 页面中使用响应式列表时没有用
Obx包裹组件,数据源变化时无法触发界面重绘 - API层不必要地给返回值加了
.obs,响应式逻辑应该统一收敛在Controller层维护
修复方案
1. 修正Controller逻辑
把原来只传布尔值的方法改为传条目索引,实际修改列表内的数据,移除无效的update()调用:
class SearchFavoriteController extends GetxController{ // 明确指定列表泛型,避免类型推断错误 RxList<FavoriteModel> favDestinationList = <FavoriteModel>[].obs; @override void onInit() { super.onInit(); getFavDestination(); } Future<void> getFavDestination() async{ try{ final List<FavoriteModel> destination = await Api().getfavdestinations(); favDestinationList.assignAll(destination); }catch(e){ Get.snackbar('加载失败', e.toString()); } } // 入参改为条目索引,定位要修改的具体数据 void changeStatus(int index) { final oldItem = favDestinationList[index]; // 替换对应索引的条目,RxList会自动监听变化触发界面刷新 favDestinationList[index] = FavoriteModel( id: oldItem.id, name: oldItem.name, isfav: !oldItem.isfav, ); } }
2. 修正页面代码
用Obx包裹响应式的ListView,点击收藏按钮时传入当前条目索引,删除重复的ListView代码块即可:
Obx(() => ListView.builder( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, padding: EdgeInsets.zero, scrollDirection: Axis.vertical, itemCount: controller.favDestinationList.length, itemBuilder: (BuildContext context, int index) { final currentItem = controller.favDestinationList[index]; return Container( width: MediaQuery.of(context).size.width * 0.9, child: Row( children: [ IconButton( icon: FaIcon( currentItem.isfav ? FontAwesomeIcons.solidHeart : FontAwesomeIcons.heart, color: secondaryHeaderColor, ), onPressed: () { controller.changeStatus(index); }, ), Padding( padding: const EdgeInsets.all(8.0), child: Text(currentItem.name), ) ], ), ); } ))
3. 修正API层代码
移除API返回值多余的.obs包裹,仅返回普通数据列表即可:
List<FavoriteModel> getfavdestinations() { return [ FavoriteModel(id: '1', name: 'Germany', isfav: false), FavoriteModel(id: '2', name: 'Turkey', isfav: true), FavoriteModel(id: '3', name: 'Jordan', isfav: false), FavoriteModel(id: '4', name: 'London', isfav: false) ]; }
可选优化
如果不想每次修改收藏状态都新建Model对象,可以把FavoriteModel的isfav字段改成响应式类型,直接修改属性即可触发刷新:
class FavoriteModel { final String id; final String name; final RxBool isfav; FavoriteModel({ required this.id, required this.name, required bool isfav }) : isfav = isfav.obs; }
对应的changeStatus方法可以简化为:
void changeStatus(int index) { // toggle()是RxBool自带的取反方法,修改后自动触发刷新 favDestinationList[index].isfav.toggle(); }
内容的提问来源于stack exchange,提问作者mar
相关产品推荐
相关产品推荐

