FragmentManager中的内存泄漏

时间:2015-01-13 00:14:53

标签: android android-fragments memory-leaks

更新

我认为泄漏来自getActivity().getSupportLoaderManager().restartLoader(getLoaderId(), null, this); 我有我的对象实现LoaderCallback。有没有办法让我清除回调我厌倦了设置

getActivity().getSupportLoaderManager().restartLoader(getLoaderId(), null, null);

但这会崩溃

原稿:

我的一个片段(A)中有一个对象列表。当我向前导航时,我将片段A添加到backstack。我导航到一个新的片段后,我转储堆。我仍然在堆中看到我的对象。当我在转储中获得最短路径时,它看起来像下面。我可以看到在FragmentManagerImpl中有一个对mActive片段中片段A的引用,它使我的列表对象保持活着状态。

memory leak

我的片段是否应该留在母片中或者这是泄漏吗?

添加到backstack

FragmentTransaction transaction = mFragmentManager.beginTransaction();
updateTransactionWith(info.getReplacement(), transaction, "replace");
transaction.addToBackStack(info.getReplacement().getClass().toString());
transaction.commit();
mFragmentManager.executePendingTransactions();

2 个答案:

答案 0 :(得分:1)

通过致电addToBackStack(),您要求FragmentManager被替换的Fragment只是已停止而非已销毁因为您要么预期按下后退按钮很可能,或者Fragment在初始化时很重,并且您仍然希望避免再次执行此操作,即使用户不太可能返回。

docs明确指出

  

如果您在执行交易时未调用 addToBackStack()   删除片段,然后该片段销毁时   事务已提交,用户无法导航回来。

     

然而,如果您在删除片段时调用 addToBackStack() ,   然后片段停止,如果用户导航,将恢复   回来。

因此,它不是内存泄漏,您的观察结果与预期行为完全一致。

但是,就像Activity一样,如果系统内存不足,系统仍可选择销毁Fragment。但是,这也是预期的行为。

答案 1 :(得分:0)

这不是内存泄漏。您需要决定如何处理片段的状态。

理想情况下,您实施onSaveInstanceStateonViewStateRestored将您的状态保存到捆绑包并分别从捆绑包中恢复。

或者,如果您能够轻松地重新创建状态,则可能需要使用包来保存(重新)存储它的麻烦,并在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();