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)
出现这个问题,没有报具体哪一行代码报错,只知道是RecyclerView的问题。
网上的办法是inflater.inflate参数改为null或者false。
但不是这种情况。
搜到一个文章:
https://github.com/CymChad/BaseRecyclerViewAdapterHelper/issues/2796
发现他的问题是空布局被不同的RecyclerView重复利用导致的。
恰好我的代码里面也有一个用到空布局的地方。
mAdapter.setHomeInfos(mHomeInfos, true);
public void setHomeInfos(ArrayList<HomeInfo> homeInfos, boolean displayEmptyView) {
setShouldDisplayEmptyView(displayEmptyView);
试了一下我的app,发现确实在连续两次用到空布局的时候才会报错。
找到这个空布局创建的地方
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;
}
发现这个方法可行。
最后看一下,为什么这个方法可行,先找到抛出这个错误的地方:
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());
最后发现报错那个地方的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;
}