报错的信息是:IndexOutOfBoundsException: Inconsistency detected. Invalid item position,但是根据错误日志完全不知道是哪里出错。
后来经过Debug调试一步步排查,确定了错误的位置所在,相关代码如下:
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { page = 1; clearCache(); mIsRefreshing = true; getGankMeizi(); } });
注意这里的clearCache(); 重点就在这里,使用RecyclerView加SwipeRefreshLayout的时候,如果绑定的 List 对象在更新数据之前进行了 clear,而这时用户紧接着迅速上滑RecycleView,就会造成崩溃,而且异常不会报到你的代码上,属于RecycleView的内部错误。原因是,当你 clear 了 list 之后,这时迅速上滑,而新数据还没到来,导致 RecycleView 要更新加载下面的 Item 时候,找不到数据源了,造成程序直接崩溃了.
解决方案:
很明显,更新数据之前 clear list 是挺常见的做法,你不可能祈祷用户这时候乖乖不动等待新数据加载完,所以根本就是不合理的。
Stack Overflow 上也有这个问题,未能够解决: [How to change contents of RecyclerView while scrolling] (http://stackoverflow.com/questions/26827222/how-to-change-contents-of-recyclerview-while-scrolling)
Google code 论坛上也有这个 issue,一堆跟帖,都是描述如何重现,未能够解决: [https://code.google.com/p/android/issues/detail?id=77846] (https://code.google.com/p/android/issues/detail?id=77846)
下边是我的解决方案:
private void setRecycleScrollBug() {
mRecyclerView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (mIsRefreshing) { return true; } else { return false; } } }); }
代码很简单,就是设置一个boolean值,下拉刷新时设为true,刷新完毕后设为false,这样下拉拉取新数据时, 这时拦截RecycleView的滑动事件,禁止用户去手动向上滑动RecyclerView,暂时很完美的解决了这个问题,但是目前还没找到更好的解决办法,这个Bug目前到现在更新到 com.android.support:design:25.0.0,Google还是没有很完美的解决这个问题。