仅将 RecyclerView 中的视图动态添加到当前项目

Dynamically adding Views in a RecyclerView only to current item

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

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

如何解决这个问题?

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

每次添加新视图操作时,通过标签为具有新子项的项目保存信息。 (例如,在共享偏好中) 标记:在 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));
}

祝你好运

基于此:

but those previously added Views are still there, but now on the wrong item.

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

这么说吧,你有一个方法可以设置一个 view param 如果它是你的个人资料,那么代码如下,

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

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

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

层次结构将是,

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

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

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

The offscreen view cache stays aware of changes in the attached adapter, allowing a LayoutManager to reuse those views unmodified without needing to return to the adapter to rebind them.

您应该在您的子项目布局 XML 中采用任何空布局,例如 Linearlayout,然后在滚动列表时以这种方式将视图添加到您的特定项目的 LinearLayout 中您添加到 LinearLayout 的子视图中的一些也会随着该项目滚动。

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

其次,为什么要动态添加新视图?为什么不使用不同的 VIEWTYPE,或者只是将这些视图放在布局上,然后将它们设为 visible/invisible 或 visible/gone? (相信这样效率会更高)

让我提醒你一些关于 RecyclerView 的事情,是的,当用户滚动时,viewHolder 正在被重用(很少有人可以创建,甚至超过它需要填满屏幕)。因此,如果您在 "item A" 上添加了一些视图并且用户滚动到 "item Z",则可以为该 "item Z" 重用该 viewHolder,因此会显示之前添加的视图。

你怎么解决这个问题?

如果您需要添加新视图,请始终检查每个项目,如果是,则添加它们(如果尚未添加),否则始终将这些视图(如果存在)删除到 return 默认 viewHolder 状态(或其他任何状态)你叫它)。

希望对您有所帮助。

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

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

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

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