ByRecyclerView加载更多,快速滑动导致系统崩溃ViewHolder views must not be attached when created.

5,868 阅读1分钟

1.先看演示效果(快速加载才会导致)

bug信息如下:

java.lang.IllegalStateException: ViewHolder views must not be attached when created. Ensure that you are not passing 'true' to the attachToRoot parameter of LayoutInflater.inflate(..., boolean attachToRoot)
        at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6796)
        at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5975)
        at android.support.v7.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:286)
        at android.support.v7.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:343)
        at android.support.v7.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:359)
        at android.support.v7.widget.GapWorker.prefetch(GapWorker.java:366)
        at android.support.v7.widget.GapWorker.run(GapWorker.java:397)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7682)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

这个bug纠结了我好久,中间陆陆续续又做了其他事,实在太难了,网上各种搜索都没有解决方案,有的解决方案也没有办法解决我的问题。最后是我的一个好朋友给了我灵感,延时!在加载数据的时候延时一下,结果没用。后来灵机异动,在调用适配器的notifyItemRangeChanged时候延时呢。起初延时1s,看起来也很正常,后来改为100ms,结果很完美啊

HomeAdapter代码如下:

原理:大概是RecyclerView复用问题,所以我在调用appendData()方法时,其实数据已经加载进去了,但是还没有调用notifyItemRangeChanged()方法通知列表更新,采用延时100ms的办法,在用户体验上完全没有影响,而且还解决了问题。非常完美!!!

    public void appendData(List dataSet) {
//        isLoadBanner = false;
        int positon = this.listData.size();
        if (dataSet != null && !dataSet.isEmpty()) {
            this.listData.addAll(dataSet);
//            notifyDataSetChanged();
            /**
             * 解决recyclerview刷新数据导致的闪屏
             * 用notifyItemRangeChanged方法替换notifyDataSetChanged
             */
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    notifyItemRangeChanged(positon, dataSet.size());
                }
            },100);
        }
    }