Inconsistency detected. Invalid view holder adapter position"

RecyclerView在添加數(shù)據(jù)的時候發(fā)生了異常.

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{f82aa71 position=11 id=-1, oldPos=6, pLpos:6 scrap [attachedScrap] tmpDetached not recyclable(1) no parent}
     at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5297)
     at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5479)
     at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5440)
     at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5436)
     at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2224)
     at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1551)
     at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1511)
     at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:595)
     at android.support.v7.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3534)
     at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3310)
  ...

RecyclerView#validateViewHolderForOffsetPosition(ViewHolder holder)

if (holder.mPosition < 0 || holder.mPosition >= mAdapter.getItemCount()) {
                throw new IndexOutOfBoundsException("Inconsistency detected. Invalid view holder "
                        + "adapter position" + holder);
            }

holder.mPosition >= mAdapter.getItemCount()為真,拋出了異常
發(fā)現(xiàn)mAdapter.getItemCount() 的值是正常的,但是holder.mPosition值有問題,在某種情況下和getItemCount的值一樣大,此時條件為真。

接下來看了下RecyclerView中有5個方法改變了mPosition的值,分別是

  • Adapter#bindViewHolder()
  • ViewHolder#resetInternal()
  • ViewHolder#offsetPosition()
  • ViewHolder#flagRemovedAndOffsetPosition()
  • Recycler#tryGetViewHolderForPositionByDeadline()

分別打了斷點,發(fā)現(xiàn)會引起崩潰的代碼,會改變mPosition的有其中三個地方resetInternal()offsetPosition(),bindViewHolder()
resetInternal() 首先排除 ,因為mPosition = NO_POSITION;

然后仔細查看offsetPosition()bindViewholder()中的值發(fā)現(xiàn),offsetPosition()的值mPosition += offset;會超出mPosition的值的范圍。
所以現(xiàn)在就要去找這個方法被調(diào)用的時機和offset這個值的含義

  1. 查看offsetPosition()的調(diào)用,發(fā)現(xiàn)調(diào)用分別來自RecyclerView與RecyclerView.Recycler兩個的對應(yīng)的insert,moveremove方法,以及ViewHolderflagRemovedAndOffsetPosition(int, int, boolean)的方法
    主要看就下面這個
void offsetPositionRecordsForInsert(int positionStart, int itemCount) {
  //...
   //這里將itemCount 傳遞給了offsetPosition
               holder.offsetPosition(itemCount, false);
 //...
       mRecycler.offsetPositionRecordsForInsert(positionStart, itemCount);
       requestLayout();
   }

看起來在某個刷新數(shù)據(jù)的地方理解錯了itemCount,找到我自己Adapter代碼里面的
notifyItemRangeInserted(positionStart,itemCount);暫時修改為notifyDataSetChanged()不會報錯了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容