【问题标题】:ViewHolders not recycled when reusing adapter for RecycleView使用 RecyclerView 的适配器时 ViewHolders 未回收
【发布时间】:2017-06-20 18:31:55
【问题描述】:

单击项目转到详细信息时,我有一个提要,在此期间,FeedFragment 已分离并已推送 DetailsFragment。返回时,我们正在检查适配器是否不为空。

    if (adapter == null) {
      adapter = createAdapter();
    }

    if (recyclerView.getAdapter() == null) {
      recyclerView.setAdapter(adapter);
    }

问题在于,每次查看详细信息并返回时重用适配器时,ViewHolders 的数量会增加一倍。它可以一直持续到它冻结应用并发生 OOM。

问题是为什么会这样?适配器不应该从 recyclerView 中分离出来,所有的项目都应该被回收吗?

附:返回时创建新适配器时不会出现此问题。

【问题讨论】:

  • 您确定收到 onDetach 回调吗?并且ViewHolders 的数量增加了一倍,为此您需要在适配器内部具有 clearAdaptor 函数,该函数可以清除传递给适配器的数据并通知数据集发生更改。
  • 发布createAdapter() 代码。
  • @Sanoop 我正在做public abstract FragmentTransaction detach(Fragment fragment); 但onDetach 没有发生在片段上。是的,它加倍,我专门为此目的研究了堆
  • 你有没有检查this里面的评论。
  • 是的,片段行为也可能导致这种情况

标签: android android-recyclerview


【解决方案1】:

我认为您正在泄漏 RecyclerViews(以及他们引用的所有内容,包括视图池)

RecyclerView 在适配器 (Adapter.registerAdapterDataObserver) 上注册自己,但只有在设置新适配器时才会取消注册(它从旧适配器上取消注册并在新适配器上注册)。所以适配器会保留对先前RecyclerView 实例的引用,防止它们被垃圾回收。

我能想到的解决办法是:

  • Fragment.onDestroyView() 中的适配器手动注销RecyclerView。我知道这样做的唯一方法是致电RecyclerView.setAdapter(null)

  • 每次都使用新的适配器。它应该是相对轻量级的对象,至少与RecyclerView 本身相比。

此外,如果您想避免每次都重新创建一组ViewHolders,可以在RecyclerView 实例之间共享RecycledViewPool。 (我才发现这个,不知道应该怎么用)

【讨论】:

    【解决方案2】:

    我建议的解决方案是这样的,你应该在适配器类里面有一个明确的适配器函数,

    public void clearAdaptor() {
        if (<T>dataList != null && <T>dataList.size() > 0) {
            <T>dataList.clear();
            notifyDataSetChanged();
        }
    }
    

    并且您需要在初始设置适配器后调用此函数。

        adaptorObj = new Adaptor(/**Your implementation**/);
        mRecyclerView.setAdapter(adaptorObj);
        adaptorObj.clearAdaptor();
    
        getYourData();
    

    获取数据后调用

       adaptorObj.notifyDataSetChanged();
    

    PS:如果数据是动态的,这是一个可行的解决方案,但如果数据是静态的,也可以修改。

    【讨论】:

    • 现在我在适配器@Override public void set(Collection&lt;? extends T&gt; elements) { clear(); addAll(elements); notifyDataSetChanged(); }中这样做了
    • 按照您的建议清除适配器没有帮助
    • 我现在可能会坚持创建一个新的适配器。但我很感兴趣为什么会这样。另外,我注意到onDetachedFromRecyclerView 在分离片段时也没有被调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-27
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    相关资源
    最近更新 更多