• 写在前面          

  最近忙着赶项目进度,都不知道这次博客写点啥好了,前两天碰巧遇到一个奇怪的bug,项目中未发现与异常相关的类,于是去百度、谷歌搜索,发现这是一个早就可能被写烂吐槽的RecyclerView的bug.

  • 透过现象看本质

  不知道你们遇见没有,在RecyclerView被推的如火如荼的时候,你喜欢它,你默默用它,青睐于它的健壮性。你觉得,这玩意儿都出来这么久了,一定没问题。然而,在某一次快速滑动中,Boom,崩溃了!

  先来看下logcat打的崩溃日志:


 1 java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 6(offset:6).
2 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3300)
3 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3258)
4 at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1803)
5 at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1302)
6 at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1265)
7 at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1093)
8 at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:956)
9 at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:2715)
10 at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
11 at android.view.Choreographer.doCallbacks(Choreographer.java:555)
12 at android.view.Choreographer.doFrame(Choreographer.java:524)
13 at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
14 at android.os.Handler.handleCallback(Handler.java:615)
15 at android.os.Handler.dispatchMessage(Handler.java:92)
16 at android.os.Looper.loop(Looper.java:137)
17 at android.app.ActivityThread.main(ActivityThread.java:4921)
18 at java.lang.reflect.Method.invokeNative(Native Method)
19 at java.lang.reflect.Method.invoke(Method.java:511)
20 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
21 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
22 at dalvik.system.NativeStart.main(Native Method)

  数组越界?这日志看上去根本就跟我们代码无关呀。多番Google发现,这貌似是Google程序员的锅?内部bug?这TM官方的问题,关你何事?要不不用RecyclerView了吧?

你是一个优秀的程序猿,不应该总是逃避问题,而应该思考如何去解决它。不过这说明了一个问题,人非圣贤孰能无过,连Google程序员那么牛逼的存在都会出问题。

崩溃的原因比较清楚,如果绑定的集合List中的数据和RecycerView的数据不一致的时候,调用更新方法的时候会复现。

  • 临时解决办法

    有人这么说,造成崩溃的原因极有可能是当clear了之后,迅速上滑,但由于新数据还没来,导致RecyclerView需要更新加载下面的Item的时候,找不到数据源,导致了崩溃的发生。

所以,既然如此,一定可以通过让Clear的时候,禁止RecyclerView的滑动来解决它。代码如下:

 1 private boolean mIsRefreshing=false;
2 mRecyclerView.setOnTouchListener(
3 new View.OnTouchListener() {
4 @Override
5 public boolean onTouch(View v, MotionEvent event) {
6 if (mIsRefreshing) {
7 return true;
8 } else {
9 return false;
10 }
11 }
12 }
13 );
14 //当刷新时设置
15 //mIsRefreshing=true;
16 //刷新完毕后还原为false
17 //mIsRefreshing=false;
  • 别人怎么说

人,想法,总是千奇百怪。

造成崩溃的原因其实很明显,如果你更新集合List后,调用RVAdapter的notifyXXXX方法时,adapter的更新预期接口和实际集合更新结果不同,就会出现这个异常!不信你可以随便模拟这个情况的发生。

所以有人就得到了这样的结论:

1、RVAdapter的notifyDataSetChanged方法执行后,在一定时间内,如果你更新了你的集合(无论是否在主线程更新集合),那么这个更新会实时反应到控件上,也就是说你的控件显示也会更新。

2、调用诸如notifyItemRangeInserted这样的方法之前,考虑清楚你的集合到底更新成什么样了!要注意参考结论1,结论1会影响你的判断。

  • 靠谱的解决办法

显然,上面的方法都不太好用,继续研究发现,直接采用下面的方法可以很好的解决。

经过多番研究发现,直接像下面这样,可以完美解决我们的问题。

  保证Adapter内的list和获取到的数据list不是同一个list就好.

 Class MyAdapter extends RecyclerView.Adapter{
private List<Object>mList;
... public void notifySetListDataChanged(List<Object>list){
this.mList = list;
notifySetDataChanged();
}
}

每次数据更新(只要有变动都认为是更新)都调用

adapter.notifySetListDataChanged(list);这里的list是变动更新后的数据list;

  • 写在最后

细心和耐心在编程之路显得尤为重要,只有抱着对bug0容忍的态度和决心,我们才能越过高山,发现更高更远的天空

												

偶遇RecyclerView内部Bug的更多相关文章

  1. 【知识整理】惊现RecyclerView内部Bug???别急,我们慢慢解决它~

    一.写在前面 这也是久违的一整个月没有写Blog,也是由于近期给妹纸找工作,各种坑蒙拐骗,然而都没卵用.额,广大朋友们,成都需要软件测试.线上运维.产品助理的伙伴,赶紧私聊我了.这妹纸,学习能力挺好, ...

  2. RecyclerView 和 ListView 使用对比分析

    原文地址:http://blog.coderclock.com/2016/08/08/android/RecyclerView%20%E5%92%8C%20ListView%20%E4%BD%BF%E ...

  3. Android RecyclerView与ListView比较

    RecyclerView 概述 RecyclerView 集成自 ViewGroup .RecyclerView是Android-support-V7版本中新增的一个Widgets,官方对于它的介绍是 ...

  4. 为RecyclerView的不同item项实现不同的布局(添加分类Header)

    最近在做一个应用的时候,需要为GridLayoutManager添加头部header,然后自然而然就想到了用不同的itemType去加载不同的布局. 1.实现多item布局,用不同的itemType去 ...

  5. 似曾相识的 RecyclerView

    一.常用方法 RecyclerView 与 ListView.GridView 类似,都是可以显示同一种类型 View 的集合的控件. 首先看看最简单的用法,四步走: ①接入 build.gradle ...

  6. RecyclerView全面解析

    写在前面 起深入浅出这名字的时候我是慎重又慎重的,生怕被人骂标题党,写的什么破玩意还敢说深入浅出.所以还是请大家不要抱着太高的期望,因为没有期望就没有失望,就像陈润说的,超预期嘛.全当看小说的心情来看 ...

  7. 【Android - MD】之RecyclerView的使用

    RecyclerView是Android 5.0新特性--Material Design中的一个控件,它将ListView.GridView整合到一起,可以使用极少的代码在ListView.GridV ...

  8. 项目管理实践【四】Bug跟踪管理【Bug Trace and Management】

    首先,向大家说一声抱歉,这篇文章耽误了这么久才和大家见面.至于Bug的跟踪和管理的必要性和好处,我就不在这里说了,下面介绍几款Bug跟踪和管理的软件. 一.BugNET BugNET是一个非常优秀的开 ...

  9. 关于RecyclerView你知道的不知道的都在这了(下)

    目录 目录 正文 6. Recycler 7. ItemAnimator 8. ItemDecoration 9. OnFlingListener 目录 由于本篇篇幅特长,特意做了个目录,让大伙对本篇 ...

随机推荐

  1. Calendar类进行日期操作

    import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; /** * 测试日期类 * ...

  2. 【BZOJ 4025】 (CDQ?还是整体二分?+并查集及它的恢复操作)

    4025: 二分图 Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考 ...

  3. [BZOJ1003](ZJOI 2006) 物流运输trans

    [题目描述] 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟 ...

  4. Codeforces Round #341 (Div. 2) D. Rat Kwesh and Cheese 数学

    D. Rat Kwesh and Cheese 题目连接: http://www.codeforces.com/contest/621/problem/D Description Wet Shark ...

  5. iOS framework静态库中使用xib和图片资源详解

    一.新建bundle 前2篇文章介绍了iOS 最新framework和.a静态库制作及使用全解   iOS 工程套子工程,主工程和framework工程或.a library静态库工程联调 我现在是在 ...

  6. Integer引用类型问题

    public class TestMain { public static void main(String[] args) { Integer integer = 2; go(2); System. ...

  7. 面试通用tips--来源某猎头人员

  8. node webkit (nw.js) 无法调试的结局方案之一

    之前做过nw项目,当时主要内容是由别人做的!过后回到家中,自己研究了下这方面.结果发现我自己写的nw 客户端不可以调试!在网上各种找办法,没找到,深感绝望,突然看到 (https://github.c ...

  9. eval命令的使用

    eval :     将参数组合为一个新的命令,然后交给Shell执行.读取一连串的参数,并依参数本身的内容来执行命令.常用来处理Shell脚本中的变量,参数不限数目,参数用分号";&quo ...

  10. __FILE__,__LINE__,FUNCTION__实现代码跟踪调试

    转:http://www.cnitblog.com/zouzheng/archive/2007/08/31/32691.aspx 先看下简单的初始代码:注意其编译运行后的结果. root@xuanfe ...