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)
出現(xiàn)這個問題,沒有報具體哪一行代碼報錯,只知道是RecyclerView的問題。
網(wǎng)上的辦法是inflater.inflate參數(shù)改為null或者false。
但不是這種情況。
搜到一個文章:
https://github.com/CymChad/BaseRecyclerViewAdapterHelper/issues/2796
發(fā)現(xiàn)他的問題是空布局被不同的RecyclerView重復(fù)利用導(dǎo)致的。
恰好我的代碼里面也有一個用到空布局的地方。
mAdapter.setHomeInfos(mHomeInfos, true);
public void setHomeInfos(ArrayList<HomeInfo> homeInfos, boolean displayEmptyView) {
setShouldDisplayEmptyView(displayEmptyView);
試了一下我的app,發(fā)現(xiàn)確實(shí)在連續(xù)兩次用到空布局的時候才會報錯。
找到這個空布局創(chuàng)建的地方
public View getEmptyView() {
if(mEmptyView == null){
mEmptyView = View.inflate(mContext, R.layout.common_empty_view, null);
}
return mEmptyView;
}
https://github.com/CymChad/BaseRecyclerViewAdapterHelper/issues/2796這里面提供了方法:
//在重用mEmptyLayout視圖前,先將mEmptyLayout從之前對父布局中釋放出來
ViewGroup elViewGroup = (ViewGroup)mEmptyLayout.getParent();
if (elViewGroup != null) {
elViewGroup.removeView(mEmptyLayout);
}
拿來試了一下:
public View getEmptyView() {
ViewGroup elViewGroup = (ViewGroup)mEmptyView.getParent();
if (elViewGroup != null) {
elViewGroup.removeView(mEmptyView);
}
if(mEmptyView == null){
mEmptyView = View.inflate(mContext, R.layout.common_empty_view, null);
}
return mEmptyView;
}
發(fā)現(xiàn)這個方法可行。
最后看一下,為什么這個方法可行,先找到拋出這個錯誤的地方:
RecyclerView.java:
if (holder.itemView.getParent() != null) {
throw new 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)");
}
在這個itemView的父容器為null的情況下報的錯。
再看看這個itemView是哪來的。
RecyclerView.java:
public ViewHolder(@NonNull View itemView) {
if (itemView == null) {
throw new IllegalArgumentException("itemView may not be null");
}
this.itemView = itemView;
}
我的代碼里是在這傳的
public RecyclerViewHolder(View itemView) {
super(itemView);
}
上一步:
return new RecyclerViewHolder(getEmptyView());
最后發(fā)現(xiàn)報錯那個地方的itemView。最終就是這個getEmptyView()。
所以加的這個判斷可行。
public View getEmptyView() {
ViewGroup elViewGroup = (ViewGroup)mEmptyView.getParent();
if (elViewGroup != null) {
elViewGroup.removeView(mEmptyView);
}
if(mEmptyView == null){
mEmptyView = View.inflate(mContext, R.layout.common_empty_view, null);
}
return mEmptyView;
}