RecyclerView Bug:IndexOutOfBoundsException: Inconsistency detected. Invalid item position

今早我更新了 Android Studio 1.2 Preview 和 22 版本的 sdk,包括兼容库也更新到 22.0.0,但是令人失望的是,RecyclerView 存在的一个明显的 bug 仍然没有修复:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position…

重现的方法是:使用 RecyclerView 加官方下拉刷新的时候,如果绑定的 List 对象在更新数据之前进行了 clear,而这时用户紧接着迅速上滑 RV,就会造成崩溃,而且异常不会报到你的代码上,属于RV内部错误。初次猜测是,当你 clear 了 list 之后,这时迅速上滑,而新数据还没到来,导致 RV 要更新加载下面的 Item 时候,找不到数据源了,造成 crash.

但明显,更新数据之前 clear list 是挺常见的做法,你不可能祈祷用户这时候乖乖不动等待新数据加载完,所以根本就是不合理的。

嗯,Google 有时真是令人非常失望。好在我想到了解决这个问题的方法。

就是在刷新,也就是 clear 的同时,让 RecyclerView 暂时不能够滑动,之后再允许滑动即可。代码就是在 RecyclerView 初始化的时候加上是否在刷新进而拦截手势:

mRecyclerView.setOnTouchListener(
        new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (mIsRefreshing) {
                    return true;
                } else {
                    return false;
                }
            }
        }
);

然后去改变和恢复 mIsRefreshing 这个 boolean 即可。想象中觉得如果不让用户滑动很愚蠢,但不得不这么做的时候,发现真实效果很算完美,很不错的!我想基本上使用 RecyclerView 都会遇到这个问题,所以将它整理发表出来,一起绕过这个坑吧。

  1. Pingback: kimim ben

  2. Pingback: economics tuition

  3. Pingback: M88

  4. Pingback: New Life infertility treatment

  5. Pingback: joseph shihara rukshan de saram

  6. Pingback: carpet cleaning service watford

  7. Pingback: joseph s r de saram

  8. Pingback: rhodium

  9. Pingback: economics tuition

  10. Pingback: para para dinle

  11. Pingback: Best Newspaper in India

  12. Pingback: Trisha

  13. Pingback: Best Newspaper in India

  14. Pingback: para kazanmak

  15. Pingback: Entertainment and Movie reviews with tips on how to get Website Traffic and Make Money Online.

  16. Pingback: fightinjustice

  17. Pingback: Best Magazine in India

  18. Pingback: venus factor

  19. Pingback: best muscle growth steroids

  20. Pingback: UpholsterySupplies.com.au Reviews & Contact Details

  21. Pingback: PureLocal.com.au - Australia's Business Directory

  22. Pingback: local seo Melbourne

  23. Pingback: Akantor

  24. Pingback: SEO

  25. 我这几天就折腾这个东西,没有搞好,一气之下,今天又换成ListView了

  26. 你好,你知道导致这个bug的根本原因么?或者是RecyclerView的实现原理?最近在研究RecyclerView源码,然后源码中试着修改这个bug,但一直不成功。。。

  27. 感谢楼主的分享。
    我认为这问题是由于RecyclerView的mState值的更新不同步导致。
    目前我的做法是通过队列保存添加删除的动作,通过handler来间隔处理队列中的每一个动作,目前问题是解决了,也能同时滑动。

  28. 不太明白为什么要在更新数据之前 clear list,而不是等到数据来了再 clear

    • 哈哈,赞!这个解决办法还是不错的,虽然不是非常好,但基本感知不到那短暂的失去触摸事件,也算不错。

  29. Pingback: Payday loans

  30. 请问阿婆主有跟进这个么?disable 滑动不是很好的解决方案。Google 的 dev 实际上后来发布了个 tips:https://code.google.com/p/android/issues/detail?id=77846#c32归纳一下就是每一步对于数据源的改动都需要报给 RV