在RecyclerView更細數據時出現java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder錯誤時,有如下三種解決方案:
1. 自定義類繼承LinearLayoutManager的包裝類
自定義類繼承LinearLayoutManager,重寫onLayoutChildren,捕獲異常
public class WrapContentLinearLayoutManager extends LinearLayoutManager {
public WrapContentLinearLayoutManager(Context context) {
super(context);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
super.onLayoutChildren(recycler, state);
} catch (IndexOutOfBoundsException e) {
Log.e("RecyclerView", e.getMessage());
}
}
}
2.保證外部數據集和內部數據集實時保持一致
在進行數據移除和數據增加時,務必要保證RecyclerView的Adapter中的數據集和移除/添加等操作后的數據集保持一致!
這里,前者是在該Adapter內部,不妨叫做內部數據集,后者是開發人員傳過給Adapter的,不妨叫外部數據集。更新RecyclerView數據時,需要保證外部數據集和內部數據集實時保持一致。
外部數據集同步到內部數據集,使用如下的方法:
- notifyItemRangeRemoved();
- notifyItemRangeInserted();
- notifyItemRangeChanged();
- notifyDataSetChanged();
這里對notifyDataSetChange()做些說明:
使用該方法的更新內部數據集,沒有默認的動畫效果,同時更新數據的效率頁不如上面的方法,官方不推薦使用這種方式更新數據集。
public void notifyData(List<PoiItem> poiItemList) { if (poiItemList != null) { int previousSize = mPoiItems.size(); mPoiItems.clear(); notifyItemRangeRemoved(0, previousSize); mPoiItems.addAll(poiItemList); notifyItemRangeInserted(0, poiItemList.size()); } }
每次對外部數據集做改動時,主動和內部數據集做一次同步操作,動畫效果也得到了保持
3.使用notifyDataSetChanged同步外部數據集和內部數據集
使用notifyDataSetChanged同步外部數據集和內部數據集。該方法簡單,但是失去了動畫效果,並且更新數據的性能低