如果你在界面中使用了RecyclerView,并且添加了上拉加载和下拉刷新的功能的话,一定对这个异常不会陌生。因为这个异常就时常发生在刷新清除数据的时候,刚好上拉加载的也调用了notifyDataSetChange();
然后就会跑出如下异常:
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 6(offset:6).state:9
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java)
at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java)
at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java)
at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java)
at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java)
at android.view.View.dispatchTouchEvent(View.java:7706)
所以,要怎么避免这个bug呢?这就需要把上拉加载和下拉刷新区分开来,让着两个不再同一时间发生。但是我们没有办法去阻止用户去做这样的操作,所以只能在代码上下功夫。我们举个例子
public class FragmentKaifuTodayAndTomorrow extends BaseFragment implements OnRefreshListener, ItemKaiFuKaiCeFragmentLayout.OnClickRemindListener, UserManager.IOnLogin, UserManager.IOnLoginOut { private SwipeRefreshLayout mSwipeRefreshLayout; private RecyclerView mRecyclerView; private AdapterKaiFuKaiCeTodayAndTomorrow mAdapter; private LinearLayoutManager mLinearLayoutManager; private ArrayList<KaiFuKaiCeBean> mDatas = new ArrayList<KaiFuKaiCeBean>(); private ProtocolHomeKaiFuKaiCe mProtocolHomeKaiFuKaiCe;//获取数据 private FootView mFootView; private boolean mIsLoadingMore;//是否在加载更多数据 //下拉加载更多数据时候的网络请求 private void getMoreData() { mIsLoadingMore = true;//开始请求的时候就置true标志正在加载 mProtocolHomeKaiFuKaiCe = new ProtocolHomeKaiFuKaiCe(getActivity(), mDatas.size(), Constants.SIZE, mType, new ProtocolBase.IProtocolListener() { @Override public void onSuccess(Object resultData) { if (!getActivity().isFinishing()) { mFootView.invisible(); int start = mDatas.size(); if (mProtocolHomeKaiFuKaiCe.mDatas.size() > 0) { mDatas.addAll(mProtocolHomeKaiFuKaiCe.mDatas); mAdapter.notifyItemRangeInserted(start, mProtocolHomeKaiFuKaiCe.mDatas.size()); } else { mFootView.hide(); ToastUtils.showLongToast(getActivity(), "没有更多数据"); } mProtocolHomeKaiFuKaiCe = null; mIsLoadingMore = false;//请求更多数据成功了,并且notifyItemRangeInserted之后就置false标识已
//经添加完数据
}
}
@Override
public void onFailure(int state,boolean hasCache, String errMsg) {
if (!getActivity().isFinishing()) {
ToastUtils.showLongToast(getActivity(), errMsg);
mIsLoadingMore = false;//请求数据失败了,也要更改加载标识
}
}
});
mProtocolHomeKaiFuKaiCe.postRequest();
}
@Override
public void onRefresh() {
if(mIsLoadingMore){//加载更多数据的时候不执行刷新数据请求
mSwipeRefreshLayout.setRefreshing(false);
return;
}
loadData(getContext());//刷新数据
}
@Override
protected void initViews(View convertView) {
mSwipeRefreshLayout = (SwipeRefreshLayout) convertView.findViewById(R.id.activity_kaifukaice_layout_refresh);
mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_green_light, android.R.color.holo_blue_bright, android.R.color.holo_orange_light, android.R.color.holo_red_light);
mRecyclerView = (RecyclerView) convertView.findViewById(R.id.activity_kaifukaice_layout_recyclerview);
mLinearLayoutManager = new LinearLayoutManager(getContext());
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mFootView = new FootView(getContext(), mRecyclerView);
mAdapter = new AdapterKaiFuKaiCeTodayAndTomorrow(getContext(), mDatas,mType);
mAdapter.setFooterView(mFootView.getView());
mRecyclerView.setAdapter(mAdapter);
mSwipeRefreshLayout.setOnRefreshListener(this);
mAdapter.setOnClickRemindListener(this);
mRecyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return null != mSwipeRefreshLayout && mSwipeRefreshLayout.isRefreshing();//刷新的时候不加载更多数据,刷新的时候控制列表不可滑动
}
});
}
}
这样就实现了对上拉加载滚动和下拉刷新数据请求的控制,使他们不会在同一时间发生,从而避免的异常。
本文介绍如何在使用RecyclerView并结合上拉加载和下拉刷新功能时,避免出现IndexOutOfBoundsException异常。通过控制上拉加载与下拉刷新的执行时机,确保两者不会同时触发,有效防止异常的发生。
1394

被折叠的 条评论
为什么被折叠?



