notifyDataSetChanged更新失效:ArrayList与Adapter绑定异常排查
解决Adapter无法更新新数据集的问题
你的推测完全正确!问题出在你给listAssignments重新赋值了一个新的ArrayList对象,而Adapter初始化时绑定的是旧的ArrayList引用,所以不管你怎么调用notifyDataSetChanged(),Adapter只会盯着它一开始拿到的那个旧集合,新集合根本没和它建立关联。
下面给你两种可靠的解决方法,不用每次重建Adapter:
方法一:复用原集合,不改变引用
不要直接给listAssignments赋值新的ArrayList,而是清空原集合后,把新数据添加进去:
public void onResume(){ super.onResume(); Log.d(TAG, "Entered: onResume"); // 清空原集合,注意不要重新赋值listAssignments! listAssignments.clear(); // 获取新数据并添加到原集合中 listAssignments.addAll(sPetInformationViewModel.getAssignedProviders(petId)); Log.d(TAG, "listAssignments is: " + listAssignments); // 现在调用notifyDataSetChanged就会生效,因为Adapter绑定的还是原来的集合引用 mAdapter.notifyDataSetChanged(); }
方法二:给Adapter添加setData方法,主动更新内部集合
如果觉得复用原集合不够灵活,可以在AssignmentsAdapter里加一个更新数据的方法,让Adapter自己替换内部的集合:
首先修改Adapter类:
public class AssignmentsAdapter extends RecyclerView.Adapter<AssignmentsAdapter.ViewHolder> { private Context mContext; private List<Assignment> mAssignments; public AssignmentsAdapter(Context context, List<Assignment> assignments) { mContext = context; mAssignments = assignments; } // 添加这个方法,用来更新Adapter内部的集合 public void setData(List<Assignment> newAssignments) { mAssignments = newAssignments; notifyDataSetChanged(); // 这里直接在方法里调用通知更新 } // ... 其他原有代码 }
然后在onResume里调用这个方法:
public void onResume(){ super.onResume(); Log.d(TAG, "Entered: onResume"); // 获取新数据集 List<Assignment> newAssignments = sPetInformationViewModel.getAssignedProviders(petId); Log.d(TAG, "newAssignments is: " + newAssignments); // 调用Adapter的setData方法更新数据 mAdapter.setData(newAssignments); }
为什么原来的代码不生效?
简单来说:
- 初始化Adapter时,你把
listAssignments(地址@5461)传给了Adapter,Adapter内部保存的是这个地址的引用。 - 在onResume里,你执行
listAssignments = sPetInformationViewModel.getAssignedProviders(petId);,这时候listAssignments指向了一个新的对象(地址@5594),但Adapter里的引用还是旧的@5461。 - 调用
notifyDataSetChanged()时,Adapter会检查它持有的旧集合(@5461)的变化,而这个集合已经被你清空了,所以屏幕显示为空,新集合@5594根本没被Adapter关联上。
这两种方法都能避免重建Adapter,推荐方法一(复用集合),因为它减少了对象创建的开销;如果需要更清晰的数据更新逻辑,方法二也是不错的选择。
内容的提问来源于stack exchange,提问作者Jeff
相关产品推荐
相关产品推荐

