DialogFragment 泄漏内存

Posted

技术标签:

【中文标题】DialogFragment 泄漏内存【英文标题】:DialogFragment leaking memory 【发布时间】:2016-08-18 23:25:13 【问题描述】:

在我正在开发的应用程序中,我看到 DialogFragment 中存在内存泄漏,到目前为止,修复它的唯一方法是在 DialogFragment 被破坏时删除所有视图,这是正常的事情吗?做?我正在使用自定义 ROM,因此不确定这是否与此问题有关。是否有任何理由不从对话框中删除所有视图会导致它们泄漏内存?

    @Override
    public void onDestroyView() 
        if (getView() instanceof ViewGroup) 
            ((ViewGroup)getView()).removeAllViews();
        
        super.onDestroyView();
    

【问题讨论】:

要确认它,您还应该尝试使用非 root 手机 【参考方案1】:

这也发生在我的应用上,我使用 Leakcanary 发现了泄漏。

当您有一个带有 EditText 的对话框时会发生这种情况。使用回调实现的光标闪烁在关闭包含 EditText 的视图时未正确处理。它是根据这个偶然发生的。

https://code.google.com/p/android/issues/detail?id=188551

编辑

这就是我在每个dialog.dismiss()之前所做的:

editText.setCursorVisible(false);
dismiss();

希望这会有所帮助!

【讨论】:

应该标记为正确答案。修复了我的问题。谢谢!【参考方案2】:

MemoryLeak 发生的原因有很多,一些常见的原因:

在某些静态字段中保留对象(在本例中为 DialogFragment 实例)的引用。 将 Context 传递给 ThreadAsyncTask,因为 Threads 也是 GC root! 您的类具有非静态内部类,在这种情况下,如果内部类与 GC 根相关(例如,如果内部类是 AsyncTask 的实例),则会发生内存泄漏。

在您的情况下,您可能有一个与 GC root 相关的视图,而该视图不能被垃圾收集,而您保留视图的对话框也不能被垃圾收集。

【讨论】:

【参考方案3】:

我的出现可能与您的经验无关,但它确实与从 DialogFragment 中的 EditText 小部件捕获用户输入并通过回调将其发送到调用 Fragment 有关。 Leakcanary 给了我以下信息:

====================================
HEAP ANALYSIS RESULT
====================================
1 APPLICATION LEAKS

References underlined with "~~~" are likely causes.
Learn more at https://squ.re/leaks.

99628 bytes retained by leaking objects
Signature: d189c386cd77f5b37c0a05eb1a290629edee
┬───
│ GC Root: System class
│
├─ com.example.jbiss.petminder.dialogs.DurationDialogFragment class
│    Leaking: NO (a class is never leaking)
│    ↓ static DurationDialogFragment.mCallback
│                                    ~~~~~~~~~
╰→ com.example.jbiss.petminder.fragments.ScheduleAppointmentFragment instance
Leaking: YES (ObjectWatcher was watching this because             
com.example.jbiss.petminder.fragments.ScheduleAppointmentFragment received         
Fragment#onDestroy() callback and Fragment#mFragmentManager is null)
key = 820c4d81-c97f-412b-be14-4cc17f883313
watchDurationMillis = 5169
retainedDurationMillis = 168
key = 2b74e5f3-c55c-4797-9d7a-dd2bca477a53

原来是因为我将 mCallback 声明为静态的。当我从声明中删除“静态”时,我会收到其他 DialogFragment 的 mCallback 之一的此消息。好吧,我想通了,并从所有这些 mCallback 声明中删除了“静态”,并且不再有泄漏,至少从那方面来说是这样。我不知道我为什么这样做,但我做到了,leakcanary 为我找到了它,并为我免去了未来的悲伤。

【讨论】:

以上是关于DialogFragment 泄漏内存的主要内容,如果未能解决你的问题,请参考以下文章

DialogFragment: DialogFragment的一些理解

Android DialogFragment vs Dialog

将正/负按钮添加到 DialogFragment 的 Dialog

详细解读DialogFragment

Android为啥推荐用DialogFragment创建Dialog?

android 全屏dialog dialogfragment