我已经在连续几天尝试找到ActionMode内存泄漏的源头,但一直没能成功。我的一个Activity中有多个Fragment,当我离开包含ActionMode的Fragment(同时自动取消它),LeakCanary就会检测到内存泄漏。
我已经在destroy()中将ActionMode和ActionMode.Callback都置为null,甚至尝试在onDestroyActionMode()中这样做。
以下是我的LeakCanary截图:
https://i.imgur.com/RUbdqj3.png
希望有人能指引我正确的方向。
P.S. 我怀疑问题可能与ActionMode.Callback有关。虽然我无法找到任何销毁它的方法,我使用startSupportActionMode(mActionModeCallback)启动ActionMode。我也尝试找到从中删除mActionModeCallback的方法,但没有找到任何方法。
以下是完整的ActionMode代码:
private ActionMode mActionMode;
private ActionMode.Callback mActionModeCallback;
public void startCAB()
{
if (mActionMode == null)
mActionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(mActionModeCallback);
}
private void buildActionModeCallBack()
{
mActionModeCallback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu_cab, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
... Some Code ...
}
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
mActionModeCallback = null; // Tried with and without this.
}
};
}
public void finishActionMode()
{
mActionMode.finish();
}
@Override
public void onDestroy()
{
super.onDestroy();
mActionMode = null;
mActionModeCallback = null;
}
包含片段的父活动:
@Override
public void onTabUnselected(TabLayout.Tab tab)
{
clearCAB();
}
private void clearCAB()
{
int index = mPagerAdapter.getCurrentFragmentIndex();
FragmentOne fragmentOne = (FragmentOne) mPagerAdapter.instantiateItem(mViewPager, index);
fragmentOne.finishActionMode();
}
mActionMode.finish()
而不是显式地将引用设置为null
吗? - earthw0rmjimActionMode.Callback
。一旦调用了AppCompatActivity.startSupportActionMode(mActionModeCallback)
,就再也没有取消引用ActionMode.Callback
,因此回调始终具有强引用。解决方案是创建一个具体的回调实现,其生命周期与应用程序相同,然后自己设置/取消自定义回调实现中的变量,这样整个片段就不会泄漏 - 这是aosp的错误。 - Mark