RecyclerView:如何清除来自RecyclerView.RecycledViewPool的回收视图

9

这里是情况: RecyclerView的item视图具有复杂的布局。
在某个时刻,我通过以下方式修改RecyclerView项的布局:
例如:修改后的视图在itemView内的索引为3;

for (int i=0; i < mRecyclerView.getChildCount(); i++) {

    ViewGroup itemView = ((ViewGroup) mRecyclerView.getChildAt(i));

    itemView.getChildAt(3).getLayoutParams().width = newWidth;
    itemView.getChildAt(3).requestLayout();
} 

一切都按预期工作,但是当我滚动RecyclerView时,会出现2-3个已回收的项目视图,其宽度仍旧是旧的。现在我正在尝试找到如何从RecycledViewPool中删除这些视图,甚至更好的解决方案:修改它们的宽度,但我无法找到获取这些视图的方法。

我尝试了 mRecyclerView.getRecycledViewPool().clear() ,但旧视图仍然会重新出现。


在执行mRecyclerView.getRecycledViewPool().clear()和mAdapter.notifyDataSetChanged()之后,您需要进行通知。 - vikas kumar
6个回答

11

为了防止RecyclerView缓存已解绑但未回收的视图,请使用:

mRecyclerView.setItemViewCacheSize(0)

另一种稍微激进的方式是调用notifyDataSetChanged()notifyItemChanged(),针对你期望被缓存的项 - 这将强制它们被回收并且你可以在onBindViewHolder()中更新它们


太好了!如果你想在适配器内部操作视图,它是最有效的。 - Raj kannan Iyyappan

2

我没有找到从RecycledViewPool中获取视图的方法,但我发现还有一些视图与RecyclerView分离,但尚未被回收。因此,如果您想修改所有itemViews内部视图的宽度,这是真正有效的解决方案。
例如:要修改itemView内已修改视图的索引= 3;
首先修改所有可见视图的宽度:

for (int i=0; i < mRecyclerView.getChildCount(); i++) {

    ViewGroup itemView = ((ViewGroup) mRecyclerView.getChildAt(i));

    itemView.getChildAt(3).getLayoutParams().width = newWidth;
    itemView.getChildAt(3).requestLayout();
} 

修改从RecyclerView中分离出来的itemViews的宽度。这包括已回收的itemViews和未回收但已分离的views。

@Override
public void onViewAttachedToWindow(ViewHolder holder) {
    super.onViewAttachedToWindow(holder);

    ((ViewGroup) holder.itemView).getChildAt(3).getLayoutParams().width = newWidth;
}

1

请尝试以下方法:

  1. 初始化时:
recyclerView.setItemViewCacheSize(0);

当刷新数据时:
recyclerView.removeAllViews();

recyclerView.getRecycledViewPool().clear();

0

我也有同样的问题。我最初在我的RecyclerView中使用了一些项目集。当到达最后一个索引时,我添加了一些数据。添加的数据重叠了前一个视图的视图。在回收时,必须删除先前的视图。但它不会删除该视图。因此,我使用了以下代码:

public override void OnViewRecycled(Java.Lang.Object holder)
    {
        var MyHolder = holder as ViewHolder;
        (MyHolder.ItemView as ImageView).RemoveAllViewsInLayout();
        base.OnViewRecycled(MyHolder);

    }

在RecyclerView中,我们有像OnViewRecycled这样的重写方法。通过清除视图持有者视图,我们可以刷新视图。

0
adapter.notifyItemRangeRemoved(0,adapter.getItemCount());

在 for 循环之前只需这样做。


我的应用程序在每次项目数量与回收器适配器上的项目位置发生冲突时都会崩溃。在“Adapter.notifyDataSetChanged();”之前的那一行代码解决了我在Android SDK 31上的崩溃问题。 - Miguel Tomás

0

只需在您的适配器中添加此代码:

public class YourAdapter extends RecyclerView.Adapter<YourAdapter.YourViewHolder> {

...

private RecyclerView parent;

@NonNull
@Override
public YourAdapter.YourViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    this.parent = ((RecyclerView) parent);
...
}

@Override public void onViewRecycled(@NonNull YourViewHolder holder) {
    parent.getRecycledViewPool().clear();
    setLayoutParamsToView(holder.itemView);
}

...

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接