【问题标题】:Backstack and memory leakage回栈和内存泄漏
【发布时间】:2013-07-20 15:02:40
【问题描述】:

我基于 Google 支持库开发了一个用于对话框片段的小型 API,要求非常简单:

  • API 可以添加(或替换)模式对话框
  • API 可以通过编程方式关闭对话框,或者用户可以通过按下按钮关闭对话框

我的 API 是否会因为不断地向 backstack 添加片段而造成内存泄漏?

public class DialogFragmentUtils {

private static final String DIALOG_TAG = "dialogTag";

public static void showDialogFragment(@Nullable Activity activity, @NotNull Fragment fragment) {
    if (activity instanceof FragmentActivity) {
        FragmentActivity fragmentActivity = (FragmentActivity) activity;
        FragmentManager fm = fragmentActivity.getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        Fragment prev = fm.findFragmentByTag(DIALOG_TAG);
        if (prev != null && prev.isAdded()) {
            ft.remove(prev);
        }
        ft.add(fragment, DIALOG_TAG);
        ft.addToBackStack(null);
        ft.commit();
    }
}

public static void dismissDialogFragment(@Nullable Activity activity) {
    if (activity instanceof FragmentActivity) {
        FragmentActivity fragmentActivity = (FragmentActivity) activity;
        FragmentManager fm = fragmentActivity.getSupportFragmentManager();
        DialogFragment dialog = (DialogFragment) fm.findFragmentByTag(DIALOG_TAG);
        if (dialog != null) {
            dialog.dismiss();
        }
    }
}
}

【问题讨论】:

  • 由于您担心内存泄漏,我们讨论了多少对话框?
  • 你为什么不检查一下?创建多个对话框并以各种方式关闭它们(返回/确定)。然后使用 Eclipse MAT 运行堆转储并在堆中搜索对话框的实例。

标签: android fragment


【解决方案1】:

我相信它不会泄漏,但要确保您需要对其进行测试。正如talkol所说,您应该使用Eclipse MAT来分析这个问题。 vogel here 有一个很好的指南,Android 博客 here 上有一个很好的指南。创建并关闭一堆对话框,看看是否有什么不同。

附带说明为什么在 showDialogFragment() 方法中使用 ft.close() 而不是 prev.dismiss()。关闭对话框的正确方法是dismiss()

【讨论】:

  • 我不使用 ft.close()。我使用 ft.remove() 从后台堆栈中删除。
【解决方案2】:

是的,它容易出现内存不足,但不会出现内存泄漏。所有回栈Fragment 都通过硬引用保存在内存中。因此,如果您在后台堆栈中保留大量的 Fragments,那么您将耗尽内存。

看看这里:When a Fragment is replaced and put in the back stack (or removed) does it stay in memory?

更新:我看到你的DIALOG_TAG 没有改变,所以你一次只在后台保留一个Fragment,因为如果旧的存在的话,你会删除它。在这种情况下,您可能不会遇到内存不足的问题。

【讨论】:

  • 他在哪里删除旧的? dismiss()ing 它与删除它不一样!在这种情况下,我有理由确定 backstack 只会增长。
  • 看看他的showDialogFragment()方法,他调用ft.remove(prev);。他在添加之前删除了前一个。
  • 糟糕,抱歉,第一次错过了。
猜你喜欢
  • 1970-01-01
  • 2010-12-02
  • 2013-11-08
  • 2016-05-03
  • 2011-11-25
  • 2010-11-19
  • 2014-09-27
  • 2013-07-31
  • 1970-01-01
相关资源
最近更新 更多