1、Crash異常信息
最近在公司項目中開始使用RecycleView,報了一個Crash:
2亏推、原因分析
我的項目中遇到的問題是,在下載管理器的下載中tab里满葛,當某個應用下載完畢時径簿,從下載列表中remove移除這個item,會報Inconsistency detected的錯誤而導致程序崩潰嘀韧。
" Inconsistency detected. Invalid view holder adapter"的大概意思就是 數據不一致篇亭,無效的視圖適配器。
以下是項目中導致crash的方法:
public void removeData(T data) {
if (data != null) {
int position = getItemPosition(data);
if(position!=-1){
this.mDatas.remove(position);
}
}
}
mDatas是數據源 ArrayList锄贷,推測:數據源的這條數據被移除了译蒂,但是并沒有刷新 Apdater視圖,所以導致崩潰谊却?
3柔昼、解決方案
3.1 notifyItemRemoved(position)
于是在移除item的時候加上刷新Recycleview Adapter的一行代碼notifyItemRemoved(position);
public void removeData(T data) {
if (data != null) {
int position = getItemPosition(data);
if(position!=-1){
this.mDatas.remove(position);
notifyItemRemoved(position);//如果少了這一句,會報Inconsistency detected異常而崩潰
}
}
}
運行程序炎辨,嘗試復現問題捕透,果然發(fā)現正常了。
所以碴萧,在進行數據移除時乙嘀,務必要保證RecyclerView.Adapter中的數據和移除的數據源保持一致!
3.2 直接捕獲這個異常
- 創(chuàng)建一個類WrapContentGridLayoutManager繼承GridLayoutManager破喻,重寫onLayoutChildren方法
*
* 為了解決RecyclerView的官方bug:Inconsistency detected. Invalid view holder adapter
*/
public class WrapContentGridLayoutManager extends GridLayoutManager {
public WrapContentGridLayoutManager(Context context, int spanCount) {
super(context, spanCount);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
super.onLayoutChildren(recycler, state);
}catch (IndexOutOfBoundsException e){
//手動catch住
e.printStackTrace();
DebugLog.d("WrapContentGridLayoutManager","手動捕獲異常:"+e.getMessage());
}
}
}
- 設置RecyclerView的布局管理為WrapContentGridLayoutManager對象
rv = (RecyclerView) view.findViewById(R.id.app_recycler_view);
rv.setLayoutManager(new WrapContentGridLayoutManager(mContext,6));
其實手動捕獲catch住這個異常 并不是什么好的解決方法虎谢,但是我更新到最新的V7包下RecyclerView控件,發(fā)現官方也還是沒有修復這個bug曹质,所以也只能暫時這么處理了婴噩。
4、參考
https://code.google.com/p/android/issues/detail?id=77846(google官方group討論組里有提到)