【问题标题】:Dynamically adding Views in a RecyclerView only to current item仅将 RecyclerView 中的视图动态添加到当前项目
【发布时间】:2015-12-31 22:22:57
【问题描述】:

我正在动态地将视图添加到 RecyclerView 中的项目。这些添加的视图应该只与它们添加到的项目相关,但是当我滚动时我遇到了问题。似乎View 被回收并加载了一个新项目,但之前添加的那些视图仍然存在,只是现在在错误的项目上。

我假设这只是因为 ViewHolder 被重复使用,所以添加的项目在加载时再次显示为新项目。

如何解决这个问题?

【问题讨论】:

  • 请分享您的适配器类代码
  • 只是为了明确您是动态添加项目到 recyclerView 还是添加新视图并动态填充数据?
  • @CQM 对我的上述评论有什么答案吗?
  • @AnuragSingh 是的,但我最终将代码添加到 onViewRecycled 并在那里的查看器上使用“removeAllViews”。效果很好。
  • 对于任何相关的人,我对类似问题的回答应该会有所帮助stackoverflow.com/questions/32332381/…

标签: android android-recyclerview android-viewholder


【解决方案1】:

这是我的一个老问题。悬赏金,因此人气飙升和多个新的和不相关的答案。

正如我对this answer 的评论和@CQM 在我原始问题下方的评论中所述,答案是覆盖onViewRecycled() 方法并在那里执行任何需要的操作。该方法在视图被回收时调用,任何清理操作都可以在这里进行。

可以在here找到有关此方法的文档。

在我的情况下,这是删除附加到视图的不可见 TextView 的问题。案文本身已被删除,但观点仍然存在。如果许多不可见的TextView 堆积在视图上并且在滚动时没有正确回收,则滚动将开始滞后。

【讨论】:

    【解决方案2】:

    您需要根据支持数据跟踪已添加的视图。我可能会在onBindViewHolder() 中添加任何必要的额外视图,并删除onViewRecycled() 中可能存在的任何视图。然后当你想让一个动态出现时,改变你跟踪它是否应该可见的任何变量,然后调用notifyItemChanged()

    【讨论】:

    • 所以我实现了onViewRecycled,目前正在循环浏览布局中的所有子布局,我也添加了新视图,然后通过instanceof检查它们是否是我的视图类型需要删除,如果是,则删除它们。有没有更简单的方法可以从视图组中删除所有类型的视图?另外,不太清楚你最后一句话是什么意思。我目前在onBindViewHolder 中添加新视图,因为每个新视图的数据都包含在我的数据列表中。我不能只切换视图的可见性,因为我是动态添加它们的。
    【解决方案3】:

    基于此:

    但之前添加的那些视图仍然存在,但现在在错误的项目上。

    基本上,根据RecyclerView 文档,您必须每次在onBindViewHolder() 方法中重置视图,

    假设您有一个方法可以设置 view 参数,如果它是您的个人资料,那么相同的代码如下所示,

    if (list.get(position).getId()==PreferenceManager.getUserID())
    {
      // do some view change here
    setViewParam(true);
    }else
    {
      // reset the view change here
    setViewParam(false);
    }
    

    所以你在这里做的是给回收的 ViewHolder 一个重置的机会。 如果您需要帮助,请发表评论!

    【讨论】:

      【解决方案4】:

      你可以用这个! setItemViewCacheSize(int size) 在这里查看RecyclerViewDocumentation

      屏幕外视图缓存会一直感知附加适配器中的更改,从而允许 LayoutManager 重用未修改的视图,而无需返回到适配器重新绑定它们。

      【讨论】:

        【解决方案5】:

        首先,你能再分享一些代码吗?

        其次,为什么要动态添加新视图?你为什么不使用不同的 VIEWTYPE 或者只是在你的布局上已经有了这些视图,只是让它们可见/不可见或可见/消失? (我相信这样会更有效率)。

        让我提醒你一些关于 RecyclerView 的事情,是的,当用户滚动时 viewHolder 正在被重用(其中很少可以创建,甚至超过了填满屏幕所需的数量)。因此,如果您在“项目 A”上添加了一些视图并且用户滚动到“项目 Z”,则该 viewHolder 可以重复用于该“项目 Z”,从而显示之前添加的视图。

        你怎么解决这个问题?

        如果您需要添加新视图,请务必检查每个项目,如果需要添加它们(如果尚未添加),否则请始终删除这些视图(如果存在)以返回默认 viewHolder 状态(或您所称的任何内容)。

        希望这会对你有所帮助。

        【讨论】:

        • 因为要添加的视图数量是可变的。例如,用户可以为每条记录添加 0 个自定义标签或任意数量。
        【解决方案6】:

        每次发生 Add newView 操作时,通过标签为具有新子项的项目保存信息。 (例如在共享偏好中) 标签:在BindViewHolder上使用项目位置创建。

        ...
        SharedPreference  sharedPref = getSharedPreference("text" + position, context);
        SharedPreference.Editor editor = sharedPref.edit();
        editor.putString("view", "ImageView");
        ...
        

        当加载适配器获取此值并将默认设置为空时。 我不确定它的效率,但我会工作。

        ...
        String viewType = sharedPref.getString("view", null);
        //it will return ImageView 
        

        如果您知道一些可能的视图类型,例如总是会是 ImageView 和 TextView,那么使用一些 if 语句就可以了。

        if(viewType.equals("ImageVIew")){
        item(position).addView(new ImageVIew(context));
        }
        

        祝你好运

        【讨论】:

        • 不要这样做。滚动时,您将非常快速地访问和存储共享首选项。
        【解决方案7】:

        recyclerView 的适配器类中, 在onBindViewHolder 方法中, 创建另一个适配器并为您的新适配器执行相同的方法。

        层次结构是,

        mainRecyclerView -> item1(->childRecyclerView1) , item2(->childRecyclerView2), item3(->childRecyclerView3)

        这样你就可以实现你想要的,而不会在错误的项目上看到错误的值。

        【讨论】:

          【解决方案8】:

          您应该在您的子项目布局XML 中采用任何空布局,例如Linearlayout,然后在滚动列出您添加的所有子视图时以这种方式将视图添加到您的特定项目的LinearLayoutLinearLayout 也滚动该项目。

          【讨论】:

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