重用RecycleView

时间:2017-06-20 08:54:10

标签: android android-recyclerview

点击项目时我有一个Feed转到详细信息,在它分离FeedFragment并推送DetailsFragment。回去时我们正在检查适配器是否为空。

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

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

问题在于每次重新使用适配器时都会返回详细信息并返回ViewHolders的数量加倍。它可以继续,直到它将冻结应用程序和OOM发生。

问题是为什么会发生这种情况?难道适配器不能与recyclerView分离,所有项目都应该回收吗?

P.S。在返回时创建新适配器时不会发生此问题。

2 个答案:

答案 0 :(得分:4)

我认为您正在泄漏RecyclerView s(及其引用的所有内容,包括视图池)

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

我能想到的解决方案是:

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

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

另外,如果您希望每次都避免重新创建一组ViewHolders,则可以在RecyclerView个实例之间共享RecycledViewPool。 (我刚刚发现了这个,我不确定它应该如何使用)

答案 1 :(得分:0)

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

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:如果数据是动态的,这是一个可行的解决方案,但如果数据是静态的,也可以修改。