• 写在前面          

  最近忙着赶项目进度,都不知道这次博客写点啥好了,前两天碰巧遇到一个奇怪的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. 正对开源工作的源码管理web (ssh协议管理) 本地如何使用SourceTree 管理

    入口: 如何产生公钥与私钥 ,以及开源中国 gitweb sshkey 的管理web 地址: 点击 “头像” ,然后再头像下面的列表选择 “ SSH Key Settings” . 接下来,完成跟着步 ...

  2. Windows命令远程执行工具Winexe

    Windows命令远程执行工具Winexe   在对Windows系统执行渗透测试中,通过各种方式可以获取目标主机的用户名和密码.这时,只要对方主机开启文件共享服务,就可以借助Winexe工具远程执行 ...

  3. 初识C#设计模式

    利用设计模式可以使我们的代码更灵活,更容易扩展,更容易维护.各种面向对象的程序设计语言都提供了基本相同的机制:比如类.继承.派生.多态等等.但是又有各自的特色,C# 中的反射机制便是一个很重要的工具, ...

  4. javascrip异步问题

    for ( var i = 1; i <= 3; i++) { setTimeout( function (){ console.log(i); }, 0); };     一般人会以为输出结果 ...

  5. request (请求对象)

    一.学习请求 学习如何获取请求行, 请求头,请求体. 1. 获取请求行 获取请求方法 String method = request.getMethod(); System.out.println(m ...

  6. Eden的退役记

    好久没更博客了, 这篇随笔不同于之前的学术性随笔.游记,只是来发泄一下自己的情感,回忆一下自己的OI经历…… 五年的OI生涯结束了 初一:懵懂的我刚接触了OI,被其功能吸引.由于运气好过了初赛,然而复 ...

  7. 【枚举】bzoj1072 [SCOI2007]排列perm

    暴力,next_permutation函数用于枚举出下一个排列.sscanf函数用于将字符串转化成数字. #include<cstdio> #include<cstring> ...

  8. Codeforces Round #344 (Div. 2) E. Product Sum 维护凸壳

    E. Product Sum 题目连接: http://www.codeforces.com/contest/631/problem/E Description Blake is the boss o ...

  9. 既然有文件后缀名,为何还需要MIME类型?

    作者:Vincross链接:https://www.zhihu.com/question/60495696/answer/204530120来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商 ...

  10. fedora19/opensuse13.1 配置svn client

    Date: 20140208Auth: Jin 一.install zypper install  subversion yum install  subversion 二.操作 1.将文件check ...