偶遇RecyclerView内部Bug
- 写在前面
最近忙着赶项目进度,都不知道这次博客写点啥好了,前两天碰巧遇到一个奇怪的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的更多相关文章
- 【知识整理】惊现RecyclerView内部Bug???别急,我们慢慢解决它~
一.写在前面 这也是久违的一整个月没有写Blog,也是由于近期给妹纸找工作,各种坑蒙拐骗,然而都没卵用.额,广大朋友们,成都需要软件测试.线上运维.产品助理的伙伴,赶紧私聊我了.这妹纸,学习能力挺好, ...
- RecyclerView 和 ListView 使用对比分析
原文地址:http://blog.coderclock.com/2016/08/08/android/RecyclerView%20%E5%92%8C%20ListView%20%E4%BD%BF%E ...
- Android RecyclerView与ListView比较
RecyclerView 概述 RecyclerView 集成自 ViewGroup .RecyclerView是Android-support-V7版本中新增的一个Widgets,官方对于它的介绍是 ...
- 为RecyclerView的不同item项实现不同的布局(添加分类Header)
最近在做一个应用的时候,需要为GridLayoutManager添加头部header,然后自然而然就想到了用不同的itemType去加载不同的布局. 1.实现多item布局,用不同的itemType去 ...
- 似曾相识的 RecyclerView
一.常用方法 RecyclerView 与 ListView.GridView 类似,都是可以显示同一种类型 View 的集合的控件. 首先看看最简单的用法,四步走: ①接入 build.gradle ...
- RecyclerView全面解析
写在前面 起深入浅出这名字的时候我是慎重又慎重的,生怕被人骂标题党,写的什么破玩意还敢说深入浅出.所以还是请大家不要抱着太高的期望,因为没有期望就没有失望,就像陈润说的,超预期嘛.全当看小说的心情来看 ...
- 【Android - MD】之RecyclerView的使用
RecyclerView是Android 5.0新特性--Material Design中的一个控件,它将ListView.GridView整合到一起,可以使用极少的代码在ListView.GridV ...
- 项目管理实践【四】Bug跟踪管理【Bug Trace and Management】
首先,向大家说一声抱歉,这篇文章耽误了这么久才和大家见面.至于Bug的跟踪和管理的必要性和好处,我就不在这里说了,下面介绍几款Bug跟踪和管理的软件. 一.BugNET BugNET是一个非常优秀的开 ...
- 关于RecyclerView你知道的不知道的都在这了(下)
目录 目录 正文 6. Recycler 7. ItemAnimator 8. ItemDecoration 9. OnFlingListener 目录 由于本篇篇幅特长,特意做了个目录,让大伙对本篇 ...
随机推荐
- go chapter 1
case 1 // helloworld.go package main import "fmt" func main() { fmt.Println("Hello, 世 ...
- 在sublime Text 3上编写并运行java程序
参考 首先肯定是安装JDK配置环境变量,这个就不多说了. 第二步下载和安装sublime Text3. 第三步,创建一个批处理文件,命名为runJava.bat,放在JDK的bin下: @ECHO O ...
- 仿苹果系统应用的apk
仿苹果系统应用的apk 韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 收集了好久的仿苹果IOS7全套apk - Android安卓综合 ...
- 【BZOJ 3238】【AHOI 2013】差异
http://www.lydsy.com/JudgeOnline/problem.php?id=3238 后缀数组裸题但是\(5\times 10^5\)貌似常数有点大就过不了?(我的sa常数那么大想 ...
- Java学习笔记(13)
StringBuffer 增加 append(boolean b) 可以添加任意类型的数据到容器中 insert(int offset,boolean b) 指定插入的索引值,插入对应的内容 ...
- [转]ibatis中井号跟美元符号区别(#、$)
Mybatis中如何在SQL语句表名中使用参数 insert into prefix_${table_name} (a, b, c) values (#{a}, #{b}, #{c}) ${} 表示直 ...
- iOS 11 安全区域适配
//解决iOS11,仅实现heightForHeaderInSection,没有实现viewForHeaderInSection方法时,section间距大的问题 [UITableView appea ...
- kevinekline----------------- SQLSERVER MVP
https://twitter.com/kekline http://kevinekline.com/worth-the-wait-why-sql-server-2008-is-great/ http ...
- 在u-boot中添加命令
转:http://www.embedu.org/Column/Column464.htm 作者:曾宏安,华清远见嵌入式学院讲师. u-boot是嵌入式系统中广泛使用的一种bootloader.它不仅支 ...
- 你可能从未听过的 Linux 发行版
Hanthana Linux 官方主页:http://www.hanthana.org Hanthana Linux 基于 Fedora,主要面向 IT 教育,默认包含额外的编/解码器及多媒体播放器. ...