一、写在前面

这也是久违的一整个月没有写Blog,也是由于近期给妹纸找工作,各种坑蒙拐骗,然而都没卵用。额,广大朋友们,成都需要软件测试、线上运维、产品助理的伙伴,赶紧私聊我了。这妹纸,学习能力挺好,资质也不错,专业成绩总体排名年级第二,保送研究生(近期已决定放弃),心动不如行动,晚了就没机会了,赶紧私信我吧。

  该文章同步发布到:

简书:http://www.jianshu.com/p/d520e6559433

CSDN:http://blog.csdn.net/nanchen_lsl/article/details/72829093

二、惊现 RecyclerView 内部bug?

扯淡就不扯淡了,咱们还是说说这个早就可能被写烂吐槽的RecyclerView的bug吧。

不知道你们遇见没有,在RecyclerView被推的如火如荼的时候,你喜欢它,你默默用它,甚至对它的健壮性(艹,这样也算是性、爱)爱不释手。你觉得,这玩意儿都出来这么久了,一定没问题。额,没毛病。然而,在某一次快速滑动中,Boom,崩溃了!瞬间打脸。

查看Log得到下面的玩意儿。

 java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 157(offset:157).state:588
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3300)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3258)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1803)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1302)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1265)
at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1093)
at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:956)
at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:2715)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
at android.view.Choreographer.doCallbacks(Choreographer.java:555)
at android.view.Choreographer.doFrame(Choreographer.java:524)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
at dalvik.system.NativeStart.main(Native Method)

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

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

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

三、怎么解决?

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

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

 private boolean mIsRefreshing=false;
mRecyclerView.setOnTouchListener(
new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mIsRefreshing) {
return true;
} else {
return false;
}
}
}
);
//当刷新时设置
//mIsRefreshing=true;
//刷新完毕后还原为false
//mIsRefreshing=false;

四、其它人的意见

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

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

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

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

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

五、解决该问题的正确姿势?

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

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

1、复写LinearLayoutManager

 package com.zxedu.ischool.common;

 import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet; /**
* Author: nanchen
* Email: liushilin520@foxmail.com
* Date: 2017-05-19 15:56
*/ public class WrapContentLinearLayoutManager extends LinearLayoutManager {
public WrapContentLinearLayoutManager(Context context) {
super(context);
} public WrapContentLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
} public WrapContentLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
} @Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
super.onLayoutChildren(recycler, state);
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
}

2、对,没错,直接更换LayoutManaer就OK了

 //        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
// 解决RecyclerView可能出现的holder数组越界Bug
mRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));

六、写在最后

请别问我为什么这样就能解决?我会大声告诉你,我也不知道!

我能怎么办,我也很无奈~

【知识整理】惊现RecyclerView内部Bug???别急,我们慢慢解决它~的更多相关文章

  1. 偶遇RecyclerView内部Bug

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

  2. 【原创】IE11惊现无厘头Crash BUG(三招搞死你的IE11,并提供可重现代码)!

    前言 很多人都知道我们在做FineUI控件库,而且我们也做了超过 9 年的时间,在和浏览器无数次的交往中,也发现了多个浏览器自身的BUG,并公开出来方便大家查阅: 分享IE7一个神奇的BUG(不是封闭 ...

  3. Kali Linux渗透基础知识整理(四):维持访问

    Kali Linux渗透基础知识整理系列文章回顾 维持访问 在获得了目标系统的访问权之后,攻击者需要进一步维持这一访问权限.使用木马程序.后门程序和rootkit来达到这一目的.维持访问是一种艺术形式 ...

  4. wifi基础知识整理

    转自 :http://blog.chinaunix.net/uid-9525959-id-3326047.html WIFI基本知识整理 这里对wifi的802.11协议中比较常见的知识做一个基本的总 ...

  5. Spring Ioc知识整理

    Ioc知识整理(一): IoC (Inversion of Control) 控制反转. 1.bean的别名 我们每个bean元素都有一个id属性,用于唯一标识实例化的一个类,其实name属性也可用来 ...

  6. ORACLE FLASHBACK DATABASE 知识整理

    1.知识储备 1)    只有SYSDBA有权执行,闪回前一定要记录当前SCN 2)    需要停机,并要求处于ARCHIVELOG模式中 3)    闪回日志不能被复用和归档,是自动管理的.RVWR ...

  7. 【OGG】OGG基础知识整理

    [OGG]OGG基础知识整理 一.GoldenGate介绍 GoldenGate软件是一种基于日志的结构化数据复制软件.GoldenGate 能够实现大量交易数据的实时捕捉.变换和投递,实现源数据库与 ...

  8. Redis知识整理

    Redis知识整理 转自:https://www.cnblogs.com/rjzheng/p/9096228.html 1.单线程模型 Redis客户端对服务端的每次调用都经历了发送命令,执行命令,返 ...

  9. Android开发——Fragment知识整理(二)

    0.  前言 Android开发中的Fragment的应用非常广泛,在Android开发--Fragment知识整理(一)中简单介绍了关于Fragment的生命周期,常用API,回退栈的应用等知识.这 ...

随机推荐

  1. Linux 入门笔记

    一开始对linux总有些抵触,黑黑的命令框不知道如何下手,这次因为工作交接的缘故需要负责之前同事的Node后端部分,node,redis这些都是部署在Linux上的,看了几次运维的同学噼里啪啦的敲命令 ...

  2. javascript实现99乘法表

    for(var i=1; i<=9; i++) { for(var j=1; j<=i;j++) { document.write(i+"x"+i+"=&qu ...

  3. C#各个版本中的新增特性详解

    序言 自从2000年初期发布以来,c#编程语言不断的得到改进,使我们能够更加清晰的编写代码,也更加容易维护我们的代码,增强的功能已经从1.0搞到啦7.0甚至7.1,每一次改过都伴随着.NET Fram ...

  4. NodeJs之http

    创建新的服务器 创建一个简单的服务 var http = require("http"); var server = http.createServer(); server.lis ...

  5. kafka入门

    1.Kafka独特设计在什么地方?2.Kafka如何搭建及创建topic.发送消息.消费消息?3.如何书写Kafka程序?4.数据传输的事务定义有哪三种?5.Kafka判断一个节点是否活着有哪两个条件 ...

  6. tcptump的使用------使用JAVA与tcpdump从网络获取原始数据

    从这里开始,就开始接触使用分布式系统处理大数据了.在处理大数据之前,需要有一个场景,否则技术工具无法嵌入现实当中,价值就会降低.我碰到的场景应该还是比较具有普遍性,因此大家可以在我的场景里先玩一遍,熟 ...

  7. bzoj3112 [Zjoi2013]防守战线

    正解:线性规划. 直接套单纯形的板子,因为所约束条件都是>=号,且目标函数为最小值,所以考虑对偶转换,转置一下原矩阵就好了. //It is made by wfj_2048~ #include ...

  8. 实现图片的循环滚动——JS的简单应用

    首先默认都了解JS的循环分支运算符等基本语法 用CSS实现简单的布局也是会的. 然后我们就可以来了解一下 [DOM 树节点] 它分为三大类:元素节点.文本节点.属性节点 文本节点跟属性节点为元素节点的 ...

  9. oracle表信息

    获取表: select table_name from user_tables; //当前用户的表 select table_name from all_tables; //所有用户的表 select ...

  10. Spring Cloud 学习笔记(一)——入门、特征、配置

    [TOC] 0 放在前面 0.1 参考文档 http://cloud.spring.io/spring-cloud-static/Brixton.SR7/ https://springcloud.cc ...