Fragment中的内存泄漏

too*_*o42 18 android memory-leaks leakcanary

我正在使用LeakCanary库来监控我的应用程序中的内存泄漏.我收到了这个内存泄漏,不知道如何追踪导致它的原因.

05-09 09:32:14.731  28497-31220/? D/LeakCanary? In com.etiennelawlor.minesweeper:0.0.21:21.
    * com.etiennelawlor.minesweeper.fragments.MinesweeperFragment has leaked:
    * GC ROOT com.google.android.gms.games.internal.GamesClientImpl$PopupLocationInfoBinderCallbacks.zzahO
    * references com.google.android.gms.games.internal.PopupManager$PopupManagerHCMR1.zzajo
    * references com.google.android.gms.games.internal.GamesClientImpl.mContext
    * references com.etiennelawlor.minesweeper.activities.MinesweeperActivity.mFragments
    * references android.app.FragmentManagerImpl.mAdded
    * references java.util.ArrayList.array
    * references array java.lang.Object[].[0]
    * leaks com.etiennelawlor.minesweeper.fragments.MinesweeperFragment instance
    * Reference Key: 2f367393-6dfd-4797-8d85-7ac52c431d07
    * Device: LGE google Nexus 5 hammerhead
    * Android Version: 5.1 API: 22
    * Durations: watch=5015ms, gc=141ms, heap dump=1978ms, analysis=23484ms
Run Code Online (Sandbox Code Playgroud)

这是我的回购:https: //github.com/lawloretienne/Minesweeper

这似乎是一个难以捉摸的.我建立了Interface一个Fragment和a之间的沟通Activity.我设置了这个mCoordinator Interface变量onAttach()然后我意识到我没有把它归零onDetach().我修复了这个问题,但仍然发生内存泄漏.有任何想法吗?

更新

我禁用了Fragment泄漏监视,我仍然收到有关泄漏活动的通知以及以下泄漏跟踪:

05-09 17:07:33.074  12934-14824/? D/LeakCanary? In com.etiennelawlor.minesweeper:0.0.21:21.
    * com.etiennelawlor.minesweeper.activities.MinesweeperActivity has leaked:
    * GC ROOT com.google.android.gms.games.internal.GamesClientImpl$PopupLocationInfoBinderCallbacks.zzahO
    * references com.google.android.gms.games.internal.PopupManager$PopupManagerHCMR1.zzajo
    * references com.google.android.gms.games.internal.GamesClientImpl.mContext
    * leaks com.etiennelawlor.minesweeper.activities.MinesweeperActivity instance
    * Reference Key: f4d06830-0e16-43a2-9750-7e2cb77ae24d
    * Device: LGE google Nexus 5 hammerhead
    * Android Version: 5.1 API: 22
    * Durations: watch=5016ms, gc=164ms, heap dump=3430ms, analysis=39535ms
Run Code Online (Sandbox Code Playgroud)

Dav*_*ser 9

文件表明,它是安全地调用connect(),即使状态为"连接"或"连接".它还表明disconnect()无论连接状态如何,您都可以安全地呼叫.因此,我会删除调用connect()和的"if"语句disconnect().但是,我怀疑这会使这种"泄漏"消失.

很显然,GamesClientImpl被存储到你的一个参考ActivityContext.我想GoogleApiClient在你打电话时会发生这种情况GoogleApiClient.Builder.build().GoogleApiClient在你Activity完成之后,我的实例仍然存在,这似乎是一个错误.但是,如果你应该叫connect()onStart()disconnect()onStop()这似乎在暗示,你可以重复使用的连接(因为onStart()onStop()可以反复调用).要做到这一点,GoogleApiClient 必须Context在你打电话后保持对你的引用disconnect().

Activity在创建时GoogleApiClient,您可以尝试使用全局应用程序上下文而不是上下文,因为全局应用程序上下文永远存在(直到进程被终止).这应该会让你的"泄漏"消失:

// Create the Google Api Client with access to Plus and Games
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
    .addConnectionCallbacks(this)
    .addOnConnectionFailedListener(this)
    .addApi(Plus.API).addScope(Plus.SCOPE_PLUS_LOGIN)
    .addApi(Games.API).addScope(Games.SCOPE_GAMES)
    .build();
Run Code Online (Sandbox Code Playgroud)


Dmi*_*ide 0

您不应该依赖onDestroy()回调执行,在某些情况下它可能不会被调用。更可靠的解决方案是将注册/注销代码放在onResume()/内onPause()

对于 Fragment 来说也是如此(当然是出于另一个原因)onDetach(),将您的敏感代码移至onStop()onPause()

  • 不是这种情况。`onDestroy` 无法被调用,因为唯一的原因是:进程被低内存杀手杀死。我相信您在进程死亡之前是否取消订阅 Google Play 服务并不重要。 (7认同)