使用 Lollipop 的转换导致内存泄漏

Memory leak using Lollipop's transitions

我正在尝试使用 RecyclerView 和 DetailActivity 实现片段(附加到 MainActivity)之间的转换。

在我的片段中,我在 onStart() 方法中添加了 RecyclerView 侦听器:

@Override
public void onStart() {
        super.onStart();
        mRecyclerItemClickListener = new RecyclerItemClickListener(getActivity(), (view, position) -> {
            Intent intent = new Intent(getActivity(), DetailActivity.class);
            intent.putExtra(ConstantsManager.POSITION_ID_KEY, mFilmsAdapter.getImdbIdByPosition(position));
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                ActivityOptionsCompat optionsCompat = ActivityOptionsCompat
                        .makeSceneTransitionAnimation(getActivity());
                ActivityCompat.startActivity(getActivity(), intent, optionsCompat.toBundle());
            } else {
                startActivity(intent);
            }
        });
        mRecyclerView.addOnItemTouchListener(mRecyclerItemClickListener);
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mTopFilmsPresenter.attachView(this);
        mTopFilmsPresenter.getFilms();
    }

您可以看到,转换从 if 块开始。在 DetailActivity 中,我在 onCreate():

中调用了以下方法
@TargetApi(Build.VERSION_CODES.KITKAT)
private void setupWindowAnimations() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Explode explode = new Explode();
            explode.setDuration(ConstantsManager.TRANSITION_DURATION);
            getWindow().setEnterTransition(explode);
            getWindow().setExitTransition(explode);
        }
    }

在 MainActivity 中我有一个几乎相似的方法,我也在 onCreate():

中调用了它
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setWindowAnimations() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Explode explode = new Explode();
            explode.setDuration(ConstantsManager.TRANSITION_DURATION);
            getWindow().setEnterTransition(explode);
            getWindow().setExitTransition(explode);
            getWindow().setReenterTransition(explode);
            getWindow().setReturnTransition(explode);
        }
    }

我还在 DetailActivity 中实现了 Transition.TransitionListener 接口,因为文档说: 转换侦听器接收来自转换的通知。通知指示转换生命周期事件。

所以我试图在 onTransitionEnd(Transition transition)、onTransitionCancel(Transition transition)onTransitionPause(Transition transition)[=45 中删除侦听器=] 回调:

    @Override
    public void onTransitionStart(Transition transition) {

    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    @Override
    public void onTransitionEnd(Transition transition) {
        transition.removeListener(this);
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    @Override
    public void onTransitionCancel(Transition transition) {
        transition.removeListener(this);
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    @Override
    public void onTransitionPause(Transition transition) {
        transition.removeListener(this);
    }

    @Override
    public void onTransitionResume(Transition transition) {

    }

我正在使用 LeakCanary 进行内存泄漏检测,它在转换后检测到内存泄漏:

所以我想知道如何删除转换侦听器以防止此内存泄漏?

确保释放 Activity 引用,因为您在 Transition class 中牢牢抓住了它。一个简单的 Transition.removeListener(this)(因为你的 activity 实现了接口)在它的 onDestroy() 方法中应该可以防止内存泄漏。

感谢Albert Vila for the . The problem lies in TransitionManager.sRunningTransitions according to this主题。