RecyclerView不会在方向更改时从适配器中注销自身 [英] RecyclerView doesn't unregister itself from the adapter on orientation change

查看:76
本文介绍了RecyclerView不会在方向更改时从适配器中注销自身的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾经在我的android应用程序中使用ListView,最近我切换到了RecyclerView,发现它在方向改变时引入了一些内存泄漏.经过进一步调查,原因显而易见了

I used to use ListView in my android application and I recently switched to RecyclerView and observed that it introduced some memory leaks on orientation change. On further investigation, the reason became apparent

设置

一个单独的activity承载一个fragment,其实例在配置更改中保留. fragment在其布局文件中包含一个RecyclerView,该文件使用自定义adapter

A single activity which hosts a fragment, the instance of which is retained across config changes. The fragment contains a single RecyclerView in its layout file that is populated using a custom adapter

向下滚动

每当为这两个视图中的任何一个设置Adapter时,它们都会向适配器注册以监视数据的更改并在UI上进行更新. ListView在配置更改时注销自己,

Whenever an Adapter is set for any of those 2 views, they register themselves with the adapter to monitor changes to the data and update on the UI. ListView unregisters itself on config changes by

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    ...

    if (mAdapter != null && mDataSetObserver != null) {
        mAdapter.unregisterDataSetObserver(mDataSetObserver);
        mDataSetObserver = null;
    }

    ...
}

不幸的是,RecyclerView没有做到这一点

Unfortunately, RecyclerView doesn't do that

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    if (mItemAnimator != null) {
        mItemAnimator.endAnimations();
    }
    mFirstLayoutComplete = false;

    stopScroll();
    mIsAttached = false;
    if (mLayout != null) {
        mLayout.onDetachedFromWindow(this, mRecycler);
    }
    removeCallbacks(mItemAnimatorRunner);
}

证明

我多次改变了方向,然后进行了堆转储,并使用Eclipse的MAT读取了它.我确实看到我的活动有很多实例,因为RecyclerView实例没有unregister,并且它们对我的活动有很强的引用!

I changed the orientation a good number of times and then took a heap dump, and read it using Eclipse's MAT. I did see that there were a good number of instances of my activity because the RecyclerView instances didn't unregister and they have strong references to my activity!!

我错过了什么吗?你们如何确保RecyclerView不会泄漏您的活动?

Am I missing something? How do you guys make sure that the RecyclerView doesn't leak your activity?

片段

public class ExampleFragment extends Fragment {

    private ExampleAdapter mAdapter = null;

    public static ExampleFragment newInstance() {
        return new ExampleFragment();
    }


    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        setupAdapterIfRequired();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_example, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setupRecyclerView(getView());
    }

    private void setupAdapterIfRequired() {
        if (mAdapter == null) {
            mAdapter = new ExampleAdapter();
        }
    }

    private void setupRecyclerView(View rootView) {
        RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.list);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
        recyclerView.setAdapter(mAdapter);
    }
}

推荐答案

将其添加到Fragment对我来说阻止了泄漏:

Adding this to Fragment stopped leaks for me:

@Override
public void onDestroyView() {
    super.onDestroyView();
    recyclerView.setAdapter(null);
}

这篇关于RecyclerView不会在方向更改时从适配器中注销自身的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆