java.lang.IllegalArgumentException: Called attach on a child which is not detached: ViewHolder{869416e position=0 id=-1, oldPos=-1, pLpos:-1}
? ? ? ? ? at android.support.v7.widget.RecyclerView$5.attachViewToParent(RecyclerView.java:774)
? ? ? ? ? at android.support.v7.widget.ChildHelper.attachViewToParent(ChildHelper.java:239)
? ? ? ? ? at android.support.v7.widget.RecyclerView.addAnimatingView(RecyclerView.java:1285)
? ? ? ? ? at android.support.v7.widget.RecyclerView.animateChange(RecyclerView.java:3854)
? ? ? Called attach on a child which is not detached意思大概是,當(dāng)前viewholder不是被綁定的(detached)。
由于RecyclerView緩存機(jī)制,未在屏幕上顯示的item會(huì)被暫時(shí)收回,即detached,所以當(dāng)調(diào)用notifyItemChanged()?時(shí),如果item不在屏幕中,就會(huì)導(dǎo)致Called attach on a child which is not detached錯(cuò)誤,還有另外一個(gè)相關(guān)的知識(shí)點(diǎn):mLayoutManager.getChildCount();?方法返回的是當(dāng)前顯示的item個(gè)數(shù),并不是adapter所有item的數(shù)量。
? ? ? 既然明白問(wèn)題的出處,那需要判斷當(dāng)前position是否在屏幕中顯示即可,LayoutManager給我們提供了相應(yīng)的方法來(lái)判斷position是否在屏幕中,我們可以通過(guò)LayoutManager獲得當(dāng)前屏幕顯示的第一個(gè)item位置,以及最后一個(gè)item位置,注意該位置是整個(gè)list中的位置 ,當(dāng)滿足position<=lastindex && position>=firstIndex?時(shí),說(shuō)明item在屏幕中,即可安心的使用notifyItemChanged()?。如果RecyclerView可以下拉刷新或添加頭部視圖,position = 0的位置可能是下拉刷新視圖或頭部視圖,那么需要根據(jù)存儲(chǔ)到成員變量preindex?中的值來(lái)計(jì)算要需要更新的item位置:int updatePos = preIndex - firstVisibleItemPosition+1,即正確位置。
示例:
//第一個(gè)可見(jiàn)的位置
? int firstVisiblePosition = ((LinearLayoutManager) mRecyclerViewOrder.getLayoutManager()).findFirstVisibleItemPosition();
//頭部不跟新
? firstVisiblePosition = firstVisiblePosition == 0 ? (firstVisiblePosition + 1) : firstVisiblePosition;
//最后一個(gè)可見(jiàn)的位置
? ? int lastVisiblePosition = ((LinearLayoutManager) mRecyclerViewOrder.getLayoutManager()).findLastVisibleItemPosition();
? ? if (mItemPosition - firstVisiblePosition >= 0 && mItemPosition <= lastVisiblePosition)
? ? ? ? ? ? ? ? myOrderTradeAdapter.notifyItemChanged(mItemPosition);//更新數(shù)據(jù)