踩坑记录:RecyclerView 局部刷新notifyItemChanged多次调用只触发一次 onBindViewHolder 的原因
1. 问题背景
在做项目的时候,RecyclerView需要使用局部刷新,使用 notifyItemChanged(position, payload) 实现局部刷新,但发现调用多次只执行了一次,第二个刷新不生效。
2. 错误示例(只处理 payloads.get(0))
@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List<Object> payloads) {Log.d(TAG, "onBindViewHolder() 执行局部刷新 position:" + position + " payloads==null:" + (payloads == null));if (payloads != null) {Log.d(TAG, "payloads大小:" + payloads.size());}Object payload = payloads.get(0); // 错误:只处理了一个 payloadif (payloads != null && !payloads.isEmpty()) {// 局部刷新操作}else{// 如果 payload 无效,或者是全量刷新,就执行完整绑定逻辑onBindViewHolder(holder, position);}
}
3.根本原因分析
去百度查阅资料和咨询AI,RecyclerView 内部会将短时间内同一个 item 的多次 notifyItemChanged(position, payload) 合并,组成一个 payload 列表。所以 payloads 是一个 list,不是单个对象。
当我发送多次notifyItemChanged(position, payload), 然后只执行一次。后面我打印方法参数List<Object> payloads日志才发现,payloads大小有很多个,所以需要循环使用才行。
4. 正确处理方式 —— 遍历 payloads 列表
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List<Object> payloads) {Log.d(TAG, "onBindViewHolder() 执行局部刷新 position:" + position + " payloads==null:" + (payloads == null));if (payloads != null) {Log.d(TAG, "payloads大小:" + payloads.size());}// Object payload = payloads.get(0); // 错误:只处理了一个 payloadif (payloads != null && !payloads.isEmpty()) {// 局部刷新操作for (int i = 0 ; i <payloads.size();i++){if ("局部刷新UI字段".equals(payloads.get(i))) {// UI更新...}}}else{// 如果 payload 无效,或者是全量刷新,就执行完整绑定逻辑onBindViewHolder(holder, position);}
}