Android Recyclerview回收视图合并

Android Recyclerview回收视图合并,android,android-viewholder,android-recyclerview,Android,Android Viewholder,Android Recyclerview,我有一个回收者的观点。我有许多不同内容类型的视图持有者 我创建的支架如下所示: /** * Create instance of * compatible viewholder * * @param viewType * @param parent * @return */ private AbstractHolder createAbstractHolder(int viewType, ViewGroup par

我有一个回收者的观点。我有许多不同内容类型的视图持有者

我创建的支架如下所示:

  /**
     * 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个项目时,它会从第五个项目中回收视图支架,我知道这是回收器视图的想法

在ViewHolder中,如果相关数据是JSON格式的,我将隐藏/显示TextView。我正在显示哈希标记(如果存在),因此在我下面的第一项中:

然后,当我向下滚动到第5个有标签的项目时(如下所示):

然后,当我向上滚动到第一项时,标签会在不应该添加的时候添加,因为没有与此对象关联的标签数据(请参见下文):

我已经调试过了,对象数据中没有混淆,没有通过代码添加标记,这是由于recyclerview recycling,这两个项都有相同的视图保持架(视图保持架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);
        }
    }
受保护的void populateTags(Listtags,TextView[]数组){
对于(int i=0;i0)populateTags(tagsList,tagsArray);
这不仅发生在第1项和第5项中,还取决于哪些视图被重用。如果有一个视图被重用用于已经显示标记的视图,则会添加重用视图中的标记。这非常糟糕,因此我发现这个问题与上面的问题相同,但建议的答案不起作用。我注意到了这通常发生在你有“if(field!=null)holder.setField(field)”之类的东西时,而没有else。这个holder是循环的,这意味着它在那里会有值,所以你需要清理或替换每个值,如果它为null,你应该为它设置null,如果不是,你应该总是写它。这很晚,但是,作为对其他人的回答。“在注释中。因此,我将我的调用从
if(tagsList.size>0)populateTags(tagsList,tagsArray);
更改为
populateTags(tagsList,tagsArray);
,因为我没有else,并且该逻辑在方法中

就是这样。希望它能对其他人有所帮助,所以我找到了这个问题。与上面的问题相同,但建议的答案不起作用。我注意到“这通常发生在您有类似于”if(field!=null)holder.setField(field)的内容时”“,没有else。持有者是循环使用的,这意味着它将在那里有值,因此您需要清除或替换每个值,如果它为null,您应该将其为null,如果它不是null,您应该始终编写它。它很晚了,但是,作为对其他人的回答。”在注释中。因此我将调用更改为从
if(tagsList.size>0)populateTags填充(tagsList,tagsArray);
populateTags(tagsList,tagsArray);
因为我没有else,而该逻辑在方法中

就是这样。希望它能对其他人有所帮助,所以我找到了这个问题。与上面的问题相同,但建议的答案不起作用。我注意到“这通常发生在您有类似“if(field!=null)holder.setField(field)”这样的问题时”,没有else。持有者是循环使用的,这意味着它将在那里有值,因此您需要清理或替换每个值,如果为null,则应为null,如果为null,则应始终编写它。虽然很晚,但作为对其他人的回答。”在注释中。因此我将调用更改为从
if(tagsList.size>0)populateTags填充(tagsList,tagsArray);
populateTags(tagsList,tagsArray);
因为我没有else,而该逻辑在方法中

就是这样。希望它能对其他人有所帮助,所以我找到了这个问题。与上面的问题相同,但建议的答案不起作用。我注意到“这通常发生在您有类似“if(field!=null)holder.setField(field)”这样的问题时”,没有else。持有者是循环使用的,这意味着它将在那里有值,因此您需要清理或替换每个值,如果为null,则应为null,如果为null,则应始终编写它。虽然很晚,但作为对其他人的回答。”在注释中。因此我将调用更改为从
if(tagsList.size>0)populateTags填充(tagsList,tagsArray);
populateTags(tagsList,tagsArray);
因为我没有else,而该逻辑在方法中


就是这样。希望它能对其他人有所帮助。

基本上,RecyclerView就是回收。它可以重复使用容器,但不会重置它们!

这意味着每次使用数据对视图持有者进行充气时,您都需要添加新数据和删除旧数据(或隐藏一些视图)。如果不这样做,您将得到以前充气对象的数据:-(

编辑: 所以,如果你的充气代码中有类似的东西

if(item.getTagsCount() > 0)
    tags.setVisibility(View.VISIBLE);
你需要把它更新成这样

if(item.getTagsCount() > 0)
    tags.setVisibility(View.VISIBLE);
else 
    tags.setVisibility(View.GONE);


当然,这只是一个示例性条件。请记住,如果您将一些数据放在ViewHolder中,您还需要防止没有数据放在那里的情况。

基本上,RecyclerView是循环使用的。它重用容器,但不会重置容器!

这意味着每次使用数据对视图持有者进行充气时,您都需要添加新数据和删除旧数据(或隐藏一些视图)。如果不这样做,您将得到以前充气对象的数据:-(

编辑: 所以,如果你的充气代码中有类似的东西

if(item.getTagsCount() > 0)
    tags.setVisibility(View.VISIBLE);
你需要把它更新成这样

if(item.getTagsCount() > 0)
    tags.setVisibility(View.VISIBLE);
else 
    tags.setVisibility(View.GONE);

当然,这只是一个示例性条件。请记住,如果您将一些数据放入了ViewHolder,您还需要防止没有数据放入其中的情况。