1. 程式人生 > >RecyclerView下拉重新整理資料的一個Bug

RecyclerView下拉重新整理資料的一個Bug

   之前在工作中使用RecyclerView下拉重新整理時出現了一個必現的Bug,原因是使用RecycleView下拉拉取新資料的時候,同時在向上滑動RecycleView時程式就崩潰了。

報錯的資訊是:IndexOutOfBoundsException: Inconsistency detected. Invalid item position,但是根據錯誤日誌完全不知道是哪裡出錯。

   後來經過Debug除錯一步步排查,確定了錯誤的位置所在,相關程式碼如下:

 mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
        {


            @Override
            public void onRefresh()
            {
                page = 1;
                clearCache();
                mIsRefreshing = true;
                getGankMeizi();
            }
        });

 注意這裡的clearCache(); 重點就在這裡,使用RecyclerView加SwipeRefreshLayout的時候,如果繫結的 List 物件在更新資料之前進行了 clear,而這時使用者緊接著迅速上滑RecycleView,就會造成崩潰,而且異常不會報到你的程式碼上,屬於RecycleView的內部錯誤。原因是,當你 clear 了 list 之後,這時迅速上滑,而新資料還沒到來,導致 RecycleView 要更新載入下面的 Item 時候,找不到資料來源了,造成程式直接崩潰了.

解決方案:

很明顯,更新資料之前 clear list 是挺常見的做法,你不可能祈禱使用者這時候乖乖不動等待新資料載入完,所以根本就是不合理的。

Stack Overflow 上也有這個問題,未能夠解決:
[How to change contents of RecyclerView while scrolling]  (http://stackoverflow.com/questions/26827222/how-to-change-contents-of-recyclerview-while-scrolling)

Google code 論壇上也有這個 issue,一堆跟帖,都是描述如何重現,未能夠解決:


[https://code.google.com/p/android/issues/detail?id=77846]  (https://code.google.com/p/android/issues/detail?id=77846)

下邊是我的解決方案:

  private void setRecycleScrollBug()
    {

        mRecyclerView.setOnTouchListener(new View.OnTouchListener()
        {

            @Override
            public boolean onTouch(View v, MotionEvent event)
            {

                if (mIsRefreshing)
                {
                    return true;
                } else
                {
                    return false;
                }
            }
        });
    }

程式碼很簡單,就是設定一個boolean值,下拉重新整理時設為true,重新整理完畢後設為false,這樣下拉拉取新資料時,
這時攔截RecycleView的滑動事件,禁止使用者去手動向上滑動RecyclerView,暫時很完美的解決了這個問題,但是目前還沒找到更好的解決辦法,這個Bug目前到現在更新到
com.android.support:design:25.0.0,Google還是沒有很完美的解決這個問題。