【问题标题】:Recyclerview Recycled viewholders mergingRecyclerview 回收的viewholders合并
【发布时间】:2015-10-21 23:17:28
【问题描述】:

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

我这样创建我的持有者:

  /**
     * 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;
    }

问题是当我向下滚动回收站视图时遇到问题,例如,当我向上滚动到第 1 项和第 5 项时,会为第 1 项和第 5 项创建视图持有者 3。 1,它从第5个项目中回收了视图持有者,我知道这是回收者视图的想法。

如果相关数据以 JSON 格式出现,我将在视图中隐藏/显示文本视图。如果存在,我将显示哈希标签,因此在下面的第一项中:

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

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

我已经调试并且对象数据没有混淆,没有通过代码添加标签,这取决于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&lt;String&gt; tagsList = feedContent.getTags(); if(tagsList.size&gt;0)populateTags(tagsList, tagsArray); 这不仅仅发生在第 1 项和第 5 项中,它取决于哪些视图被重用。如果有视图重用已显示标签的视图,则添加重用视图中的标签。非常糟糕

【问题讨论】:

    标签: android android-viewholder android-recyclerview


    【解决方案1】:

    基本上,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,您还需要防范没有数据可放入其中的情况。

    【讨论】:

    • 感谢您的回答。我认为这就是问题所在。我能问一下实现这一目标的最干净的方法是什么?
    • 如果您的意思是自动方式,则没有(除了重新膨胀视图,但这与 RecyclerView 的整个想法背道而驰)。查看一般概念的更新答案:-)
    • 对其进行了更多更新以更好地匹配您的情况。
    • 您似乎对此有所了解,您介意检查一下我在视图持有者中的 recyclerview 和图像视图遇到的类似问题吗? stackoverflow.com/questions/33283493/…提前致谢
    【解决方案2】:

    所以我在 SO 上找到了这个问题 RecyclerView adapter taking wrong values。与上述相同的问题,但建议的答案不起作用。我注意到“这通常发生在你有类似“if (field != null) holder.setField(field)”之类的东西时,没有 else。持有者被回收,这意味着它在那里会有值,所以你需要清理“在 cmets 中。因此,我将要填充的调用从 if(tagsList.size&gt;0)populateTags(tagsList, tagsArray); 更改为 populateTags(tagsList, tagsArray);,因为我没有 else 并且该逻辑在方法中。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多