更新
我认为泄漏来自getActivity().getSupportLoaderManager().restartLoader(getLoaderId(), null, this);
我有我的对象实现LoaderCallback。有没有办法让我清除回调我厌倦了设置
getActivity().getSupportLoaderManager().restartLoader(getLoaderId(), null, null);
但这会崩溃
原稿:
我的一个片段(A)中有一个对象列表。当我向前导航时,我将片段A添加到backstack。我导航到一个新的片段后,我转储堆。我仍然在堆中看到我的对象。当我在转储中获得最短路径时,它看起来像下面。我可以看到在FragmentManagerImpl中有一个对mActive片段中片段A的引用,它使我的列表对象保持活着状态。
我的片段是否应该留在母片中或者这是泄漏吗?
添加到backstack
FragmentTransaction transaction = mFragmentManager.beginTransaction();
updateTransactionWith(info.getReplacement(), transaction, "replace");
transaction.addToBackStack(info.getReplacement().getClass().toString());
transaction.commit();
mFragmentManager.executePendingTransactions();
答案 0 :(得分:1)
通过致电addToBackStack()
,您要求FragmentManager
被替换的Fragment
只是已停止而非已销毁因为您要么预期按下后退按钮很可能,或者Fragment
在初始化时很重,并且您仍然希望避免再次执行此操作,即使用户不太可能返回。
docs明确指出
如果您在执行交易时未调用 addToBackStack() 删除片段,然后该片段销毁时 事务已提交,用户无法导航回来。
然而,如果您在删除片段时调用 addToBackStack() , 然后片段停止,如果用户导航,将恢复 回来。
因此,它不是内存泄漏,您的观察结果与预期行为完全一致。
但是,就像Activity
一样,如果系统内存不足,系统仍可选择销毁此Fragment
。但是,这也是预期的行为。
答案 1 :(得分:0)
这不是内存泄漏。您需要决定如何处理片段的状态。
理想情况下,您实施onSaveInstanceState
和onViewStateRestored
将您的状态保存到捆绑包并分别从捆绑包中恢复。
或者,如果您能够轻松地重新创建状态,则可能需要使用包来保存(重新)存储它的麻烦,并在onPause
方法中将您的引用置空并创建它们在onResume
方法中。请注意,即使片段刚刚创建,onResume
也会被调用,因此请注意不要多次执行此操作。
无论哪种方式,请务必取消引用,以确保您的对象标记为GC。
FragmentManager将根据需要决定是否需要丢弃并重新创建片段,以便允许用户返回添加到堆栈中的片段。在堆栈中没有其他东西和/或有大量备用内存的情况下,它可能只是直接引用您添加到后台堆栈的片段。
考虑到所有这些,你还需要注意保持对其他片段,活动等的引用,因为这种状态很难重新创建。
建议采用以下方法提供适当的反向导航:
// Works with either the framework FragmentManager or the
// support package FragmentManager (getSupportFragmentManager).
getSupportFragmentManager().beginTransaction()
.add(detailFragment, "detail")
// Add this transaction to the back stack
.addToBackStack()
.commit();