因?yàn)镽ecyclerView在計(jì)算layout的時(shí)候不允許你更新Adapter內(nèi)容括袒。
這些notify去更新adapter的內(nèi)容時(shí)享钞,如果RcyclerView正在isComputingLayout倾鲫,就會(huì)報(bào)此錯(cuò)誤;
在recyclerView中的實(shí)現(xiàn)
在assertNotInLayoutOrScroll方法中,如果isComputingLayout為true捷犹,就會(huì)報(bào)錯(cuò)
iscomputingLayout方法如下弛饭,是通過mLayoutOrScrollCounter成員變量統(tǒng)計(jì)正在layout或scroll的item的數(shù)量
public boolean isComputingLayout() {
return mLayoutOrScrollCounter > 0;
}
上面是異常路徑,以下分析導(dǎo)致這個(gè)異常的原因
recyclerview對(duì)應(yīng)一個(gè)adapter萍歉,當(dāng)adapter中的數(shù)據(jù)發(fā)生改變時(shí)侣颂,必須通過notify方法通知recyclerview
List<TimelineItemResp> buyList = data.getPageData();
if (pageNo == 1) {
purchaseWorks.clear();
List<DataTabResp> tabList = data.getTabList();
getUI().updateFilterData(tabList, data.getBuyCount());
}
if (buyList != null ) {
if ( buyList.size() <= 0) {
getUI().setLoadMoreEnable(false);
} else {
getUI().setLoadMoreEnable(true);
purchaseWorks.addAll(buyList);
getUI().updateWorkList(purchaseWorks);
pageNo++;
}
}
setLoadMoreEnable(false);這個(gè)方法中由于業(yè)務(wù)邏輯做了一個(gè)notifyItemChanged(itemCount - 1);
updateWorkList(purchaseWorks);方法是直接給adapter。addAll枪孩,如下
網(wǎng)絡(luò)請(qǐng)求的數(shù)據(jù)憔晒,傳的是對(duì)象的地址值
public void addAll(List<T> mList) {
mDatas = mList;
notifyDataSetChanged();
}
網(wǎng)絡(luò)請(qǐng)求的數(shù)據(jù)list沒有數(shù)據(jù)時(shí),adapter中的dataList會(huì)被clear销凑,然后走notifyItemChanged(-1);丛晌,數(shù)據(jù)改變,notify錯(cuò)誤斗幼,如果不及時(shí)糾正澎蛛,就會(huì)報(bào)此錯(cuò)誤,
getAdapter().getDataList().clear();
getAdapter().notifyItemChanged(0);
getAdapter().notifyDataSetChanged();
清除數(shù)據(jù)后蜕窿,notifyitem錯(cuò)誤谋逻,然后及時(shí)調(diào)用notifyDataSetChanged糾正錯(cuò)誤,就不會(huì)出錯(cuò)桐经。
如果notifyitem錯(cuò)誤后毁兆,再繼續(xù)notifyitem,就會(huì)報(bào)錯(cuò)
如果notifyitem錯(cuò)誤后阴挣,adapter中的datalist又發(fā)生改變气堕,notifyDataSetChanged也會(huì)報(bào)錯(cuò)。
結(jié)論:adapter中的datalist數(shù)據(jù)發(fā)生改變畔咧,notify錯(cuò)誤茎芭,沒有及時(shí)糾正,或者數(shù)據(jù)又改變誓沸,也會(huì)報(bào)此錯(cuò)梅桩,所以數(shù)據(jù)改變要notify正確,比如position正確拜隧,notifyitem時(shí)一定要保證position是正確的(pos有效宿百,不越界),notifyDataSetChanged沒有這問題