使用 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主题。
我正在尝试使用 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 TransitionManager.sRunningTransitions
according to this主题。