Recyclerview 回收的viewholders合并
Recyclerview Recycled viewholders merging
我有回收站观点。我有很多针对不同内容类型的视图持有者。
我这样创建我的支架:
/**
* Create instance of
* compatible viewholder
*
* @param viewType
* @param parent
* @return
*/
private AbstractHolder createAbstractHolder(int viewType, ViewGroup parent) {
AbstractHolder holder = null;
switch (viewType) {
case VersyConstants.HOLDER_TYPE_1:
holder = ViewHolder_Var1.create(parent, mUserHomeFragment, mUserStreamFragment);
break;
case VersyConstants.HOLDER_TYPE_2:
holder = ViewHolder_Var2.create(parent, mUserHomeFragment, mUserStreamFragment);
break;
case VersyConstants.HOLDER_TYPE_3:
holder = ViewHolder_Var3.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 3");
break;
case VersyConstants.HOLDER_TYPE_4:
holder = ViewHolder_Var4.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 4");
break;
case VersyConstants.HOLDER_TYPE_5:
holder = ViewHolder_Var5.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 5");
break;
case VersyConstants.HOLDER_TYPE_6:
holder = ViewHolder_Var6.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 6");
break;
case VersyConstants.HOLDER_TYPE_7:
holder = ViewHolder_Var7.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 7");
break;
case VersyConstants.HOLDER_TYPE_8:
holder = ViewHolder_Var8.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 8");
break;
case VersyConstants.HOLDER_TYPE_9:
holder = ViewHolder_Var9.create(parent, mUserHomeFragment, mUserStreamFragment);
break;
case VersyConstants.HOLDER_TYPE_10:
holder = ViewHolder_Var10.create(parent, mThumbnailViewToLoaderMap, mUserHomeFragment, mUserStreamFragment);
}
return holder;
}
问题是当我向下滚动回收站视图时遇到的问题,例如,当我向上滚动到项目编号时,为第一项和第五项创建了视图持有者 3。 1,它有第 5 项的回收视图持有者,我知道这是回收视图的想法。
如果相关数据进入 JSON,我在 viewholders 中是 hiding/showing 文本视图。如果存在,我将显示散列标签,因此在下面的第一项中:
然后当我向下滚动到第 5 个带有标签的项目时(如下):
然后当我向上滚动到第一个项目时,标签会在不应该添加的时候添加,因为没有与此对象关联的标签数据(见下文):
我已经调试过,对象数据没有混淆,没有通过代码添加标签,这取决于recyclerview回收,这两个项目有相同的view holder(view holder 3)。有什么办法可以防止这种情况吗?
下面是填充标签的方法。根据列表大小,我将文本视图的可见性设置为可见并填充:
protected void populateTags(List<String>tags, TextView[] array){
for(int i=0;i<tags.size(); i++){
array[i].setText(tags.get(i));
array[i].setVisibility(View.VISIBLE);
}
}
上面我这样称呼List<String> tagsList = feedContent.getTags(); if(tagsList.size>0)populateTags(tagsList, tagsArray);
这不仅仅发生在第 1 项和第 5 项中,它取决于哪些视图被重用。如果有一个视图重用于已经显示标签的视图,则添加来自重用视图的标签。非常糟糕
所以我在 SO 上找到了这个问题 。与上述问题相同,但建议的答案无效。我注意到 "This usually happens when you have something like "if (field != null) holder.setField(field)", 没有 else。支架是回收的,这意味着它在那里会有值,所以你需要清理或更换每一个值,如果它为 null,你应该 nullit,如果不是,你应该写它,总是。已经晚了,但是,作为对其他人的回答。”在评论中。因此,我将调用从 if(tagsList.size>0)populateTags(tagsList, tagsArray);
更改为 populateTags(tagsList, tagsArray);
,因为我没有 else 并且该逻辑在方法中。
就是这样..希望对其他人有所帮助
基本上,RecyclerView 就是回收。它会重复使用容器,但 不会重置它们!
这意味着每次用数据填充 ViewHolder 时,都需要添加新数据并删除旧数据(或隐藏一些视图)。如果你不这样做,你最终会得到来自先前膨胀对象的数据:-(
编辑:
所以,如果你的充气代码中有这样的东西
if(item.getTagsCount() > 0)
tags.setVisibility(View.VISIBLE);
你需要更新成这样
if(item.getTagsCount() > 0)
tags.setVisibility(View.VISIBLE);
else
tags.setVisibility(View.GONE);
或
if(item.getTagsCount() > 0)
tags.setVisibility(View.VISIBLE);
else if(item.getTagsCount() == 0)
tags.setVisibility(View.GONE);
当然,这只是一个示例性条件。请记住,如果您将一些数据放入 ViewHolder,您还需要防范没有数据可放入其中的情况。
我有回收站观点。我有很多针对不同内容类型的视图持有者。
我这样创建我的支架:
/**
* Create instance of
* compatible viewholder
*
* @param viewType
* @param parent
* @return
*/
private AbstractHolder createAbstractHolder(int viewType, ViewGroup parent) {
AbstractHolder holder = null;
switch (viewType) {
case VersyConstants.HOLDER_TYPE_1:
holder = ViewHolder_Var1.create(parent, mUserHomeFragment, mUserStreamFragment);
break;
case VersyConstants.HOLDER_TYPE_2:
holder = ViewHolder_Var2.create(parent, mUserHomeFragment, mUserStreamFragment);
break;
case VersyConstants.HOLDER_TYPE_3:
holder = ViewHolder_Var3.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 3");
break;
case VersyConstants.HOLDER_TYPE_4:
holder = ViewHolder_Var4.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 4");
break;
case VersyConstants.HOLDER_TYPE_5:
holder = ViewHolder_Var5.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 5");
break;
case VersyConstants.HOLDER_TYPE_6:
holder = ViewHolder_Var6.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 6");
break;
case VersyConstants.HOLDER_TYPE_7:
holder = ViewHolder_Var7.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 7");
break;
case VersyConstants.HOLDER_TYPE_8:
holder = ViewHolder_Var8.create(parent, mUserHomeFragment, mUserStreamFragment);
L.i(getClass().getSimpleName(), "HOLDER 8");
break;
case VersyConstants.HOLDER_TYPE_9:
holder = ViewHolder_Var9.create(parent, mUserHomeFragment, mUserStreamFragment);
break;
case VersyConstants.HOLDER_TYPE_10:
holder = ViewHolder_Var10.create(parent, mThumbnailViewToLoaderMap, mUserHomeFragment, mUserStreamFragment);
}
return holder;
}
问题是当我向下滚动回收站视图时遇到的问题,例如,当我向上滚动到项目编号时,为第一项和第五项创建了视图持有者 3。 1,它有第 5 项的回收视图持有者,我知道这是回收视图的想法。
如果相关数据进入 JSON,我在 viewholders 中是 hiding/showing 文本视图。如果存在,我将显示散列标签,因此在下面的第一项中:
然后当我向下滚动到第 5 个带有标签的项目时(如下):
然后当我向上滚动到第一个项目时,标签会在不应该添加的时候添加,因为没有与此对象关联的标签数据(见下文):
我已经调试过,对象数据没有混淆,没有通过代码添加标签,这取决于recyclerview回收,这两个项目有相同的view holder(view holder 3)。有什么办法可以防止这种情况吗?
下面是填充标签的方法。根据列表大小,我将文本视图的可见性设置为可见并填充:
protected void populateTags(List<String>tags, TextView[] array){
for(int i=0;i<tags.size(); i++){
array[i].setText(tags.get(i));
array[i].setVisibility(View.VISIBLE);
}
}
上面我这样称呼List<String> tagsList = feedContent.getTags(); if(tagsList.size>0)populateTags(tagsList, tagsArray);
这不仅仅发生在第 1 项和第 5 项中,它取决于哪些视图被重用。如果有一个视图重用于已经显示标签的视图,则添加来自重用视图的标签。非常糟糕
所以我在 SO 上找到了这个问题 if(tagsList.size>0)populateTags(tagsList, tagsArray);
更改为 populateTags(tagsList, tagsArray);
,因为我没有 else 并且该逻辑在方法中。
就是这样..希望对其他人有所帮助
基本上,RecyclerView 就是回收。它会重复使用容器,但 不会重置它们!
这意味着每次用数据填充 ViewHolder 时,都需要添加新数据并删除旧数据(或隐藏一些视图)。如果你不这样做,你最终会得到来自先前膨胀对象的数据:-(
编辑: 所以,如果你的充气代码中有这样的东西
if(item.getTagsCount() > 0)
tags.setVisibility(View.VISIBLE);
你需要更新成这样
if(item.getTagsCount() > 0)
tags.setVisibility(View.VISIBLE);
else
tags.setVisibility(View.GONE);
或
if(item.getTagsCount() > 0)
tags.setVisibility(View.VISIBLE);
else if(item.getTagsCount() == 0)
tags.setVisibility(View.GONE);
当然,这只是一个示例性条件。请记住,如果您将一些数据放入 ViewHolder,您还需要防范没有数据可放入其中的情况。