Recyclerview循环查看者合并

时间:2015-10-21 23:17:28

标签: android android-recyclerview android-viewholder recycler-adapter

我有一个回收者视图。对于不同的内容类型,我有很多观看者。

我创建了这样的持有者:

  /**
     * 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 item 1 - no tags

然后当我向下滚动到第五个带有标签的项目(下方)时:Recyclerview 5th item with tags

然后,当我向后滚动到第一个项目时,标签会被添加,因为它们不应该是没有与此对象关联的标签数据(见下文):

First item  now with tags

我已经调试过了,对象数据没有混淆,没有通过代码添加标签,这是回收再循环视图,这两个项目都有相同的视图持有者(视图持有者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项和第1项中。 5,它取决于哪些视图被重用。如果有一个视图重用于已显示标记的视图,则会添加重用视图中的标记。非常糟糕

2 个答案:

答案 0 :(得分:3)

基本上,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,您还需要防止没有数据放在那里的情况。

答案 1 :(得分:0)

所以我在SO上发现了这个问题RecyclerView adapter taking wrong values。与上述问题相同,但建议的答案并不奏效。我注意到了#34;这通常发生在你有类似&#34; if(field!= null)holder.setField(field)&#34;,没有else的情况下。持有者被回收,这意味着它将具有值,所以你需要清理或替换每个值,如果它是null你应该nullit,如果不是,你应该写它,总是。已经很晚了,但作为别人的答案。&#34;在评论中。所以我改变了我的调用,从if(tagsList.size>0)populateTags(tagsList, tagsArray);填充到populateTags(tagsList, tagsArray);,因为我没有其他的东西,而且逻辑在方法中。

这就是它......希望它对别人有所帮助