当前位置: 代码迷 >> Android >> Recyclerview回收的Viewholder合并
  详细解决方案

Recyclerview回收的Viewholder合并

热度:79   发布时间:2023-08-04 10:34:21.0

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

我这样创建我的持有人:

  /**
     * 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,我将隐藏/显示textviews。 我正在显示哈希标签(如果存在),因此在下面的第一项中:

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

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

我已经调试过,对象数据中没有混淆,没有通过代码添加标签,这取决于recyclerview的回收,这两个项目都具有相同的视图持有者(视图持有者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); List<String> tagsList = feedContent.getTags(); if(tagsList.size>0)populateTags(tagsList, tagsArray); 这不仅发生在项目1和5上,还取决于要重用的视图。 如果存在已显示标签的视图重用的视图,则添加重用视图中的标签。 这很糟糕

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

这意味着每次向ViewHolder填充数据时,都需要添加新数据和删除旧数据 (或隐藏一些Views )。 如果不这样做,最终将得到先前膨胀的对象的数据:-(

编辑:所以,如果您的膨胀代码中有类似的内容

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中,还需要防止没有数据放入其中的情况。

所以我发现这个问题在SO上 。 与上述问题相同,但建议的答案无效。 我注意到“这种情况通常发生在您拥有诸如“ if(field!= null)holder.setField(field)”之类的东西时,没有其他情况。该持有人被回收,这意味着它将在那里拥有价值,因此您需要清理或替换每个值,如果为null,则应将其为null;否则,应始终将其写入。这已经很晚了,但可以作为其他答案。” 在评论中。 所以我改变了从if(tagsList.size>0)populateTags(tagsList, tagsArray); populateTags(tagsList, tagsArray); 因为我没有别的,而且逻辑在方法中。

就是这样..希望对其他人有帮助

  相关解决方案