【问题标题】:BottomSheetDialogFragment memory leak (use leakcanary)BottomSheetDialogFragment 内存泄漏(使用leakcanary)
【发布时间】:2019-02-19 05:31:15
【问题描述】:

我在 PopupDialog 中发现了内存泄漏,但我不知道为什么。

所以我注释掉了所有被覆盖的方法,但我仍然有泄漏。

BottomSheetDialog

class PopupDialog : BottomSheetDialogFragment() {

    // Annotated all methods and variable.

}

活动

fun showPopupDialog() = 
    PopupDialog().show(supportFragmentManager, "DialogTag.POPUP_DIALOG")

泄密

【问题讨论】:

  • 您是否将 context 存储在 PopupDialog 类中?
  • 不,PopupDialog 中的所有变量和方法都像上面的代码一样被注释掉了。 PopupDialog 只是一个继承自 BottomSheetDialog 的空类。
  • 可能是由于方向改变,如果是这种情况,它会泄漏 context
  • 我只是显示并关闭了对话框。
  • @dylan.kwon 你找到解决办法了吗?

标签: android memory-leaks bottom-sheet leakcanary


【解决方案1】:

如果您点击Message.obj (excluded) 节点,您将看到以下消息。

被规则匹配字段 android.os.Message#obj 排除,因为在阻塞队列上等待的线程会将最后一个出队的对象作为堆栈本地引用泄漏。因此,当 HandlerThread 空闲时,它会保留对它收到的最后一条消息的本地引用。然后该消息被回收并可以再次使用。只要所有的消息在被使用后被回收,这不会有问题,因为这些引用在被回收的时候被清除了。但是,当需要发送消息时,对话框会创建要复制的模板消息实例。这些消息模板保存对对话侦听器的引用,这很可能导致以某种方式保存对活动的引用。对话框从不回收它们的模板消息,假设这些消息实例将在对话框被 GC 时被 GC。一旦您使用对话框,这两件事的结合就会产生很大的内存泄漏可能性。这些内存泄漏可能是暂时的,但一些处理程序线程会长时间休眠。要解决此问题,您可以不时向空闲处理程序线程发布空消息。这并不容易,因为您无法访问所有处理程序线程,但广泛使用的库应该考虑为其自己的处理程序线程执行此操作。事实证明,Dalvik 和 ART 都会发生这种泄漏。

正如消息中所建议的,您可以发布到附加到主线程的 looper 的处理程序。您将在对话框关闭后执行此操作。

在主线程上创建的处理程序将附加到主线程的 looper。

所以你可以做这样的事情 existingHander.post {} 或者创建一个新的处理程序,你可以这样做Handler(Looper.getMainLooper()).post {}

来源:https://github.com/square/leakcanary/blob/master/leakcanary-android/src/main/java/com/squareup/leakcanary/AndroidExcludedRefs.java#L128

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 2017-10-26
    相关资源
    最近更新 更多