RecyclerView从其他Activity返回时显示异常的问题求助
问题现象
使用SharedPreferences存储购物/待办清单条目,首次进入页面显示正常;添加新条目(非末尾插入)返回后,RecyclerView重复显示最后一条数据,但重启应用或重新进入页面后显示恢复正常。
核心修复点
1. 数据更新后未通知RecyclerView适配器刷新
问题原因:从添加页面返回后,onResume()中调用StartDisplay()更新了items列表,但未通知适配器数据已变更。RecyclerView依赖适配器的通知来重新绑定数据,否则会复用旧的ViewHolder,导致视图显示异常。
修复代码:
在ShoppingList类的onResume()方法中,更新数据后调用适配器的刷新方法:
@Override public void onResume() { super.onResume(); StartDisplay(); adapter.notifyDataSetChanged(); // 通知适配器数据已更新 }
2. SharedPreferences返回的Map无序导致数据顺序混乱
问题原因:sharedPreferences.getAll()返回的Map在不同Android版本中可能是无序的,新插入的条目位置不可控,加上未刷新适配器,进一步加剧了视图显示错误。如果需要固定的条目顺序,建议改用有序存储方式。
可选优化:
如果需要保持条目插入顺序,可以将数据以JSON数组形式存储在SharedPreferences中,或者对获取到的items列表进行排序:
public void StartDisplay() { Map<String, ?> allEntries = sharedPreferences.getAll(); items.clear(); for (Map.Entry<String, ?> entry : allEntries.entrySet()) { String [] item_total = entry.getValue().toString().split(";",0); items.add(entry.getKey() + " " + item_total[0] + " " + item_total[1]); } // 按条目名称排序,可选 Collections.sort(items); }
注意:无需调用
allEntries.clear(),该Map是SharedPreferences返回的实例,清除操作无意义。
3. 条目移除逻辑存在潜在错误
问题原因:当前使用items.remove(item_click)删除条目,若存在相同内容的条目,会删除第一个匹配项而非点击位置的条目,导致数据与视图位置不匹配。
修复代码:
修改onItemClick()方法,按位置删除条目:
@Override public void onItemClick(View view, int position) { String item_click = adapter.getItem(position); String[] itemarray = item_click.split(" ",0); myEdit.remove(itemarray[0]); myEdit.commit(); items.remove(position); // 按位置删除,确保对应条目被移除 adapter.notifyItemRemoved(position); }
修复原理说明
RecyclerView通过ViewHolder复用机制提升性能,当数据源变化时必须调用notifyDataSetChanged()或更精细的通知方法(如notifyItemInserted()),让适配器重新绑定数据到对应的ViewHolder。未通知时,适配器仍使用旧的视图缓存,导致新数据无法正确渲染,出现重复显示最后一条的异常。
内容的提问来源于stack exchange,提问作者Ákos Szegleti

