如何使用泄漏金丝雀

我知道这可能是一个愚蠢的问题,但我是开发android的新手,我目前在我的应用程序中遇到OutOfMemoryError,我试图使用MAT调试,但是仍然很难find漏洞活动,然后我find了LeakCanary,它看起来更简单,更容易使用,但是我找不到任何有关使用Leak Canary的初学者一步一步的指南,即使在Google上也是如此。 我已经通过build.gradle中的依赖项安装了LeakCanary,这是我到目前为止所得到的:

ExampleApplication.java

public class ExampleApplication extends Application { public static RefWatcher getRefWatcher(Context context) { ExampleApplication application = (ExampleApplication) context.getApplicationContext(); return application.refWatcher; } private RefWatcher refWatcher; @Override public void onCreate() { super.onCreate(); refWatcher = LeakCanary.install(this); } final class KeyedWeakReference extends WeakReference { public final String key; public final String name; KeyedWeakReference(Object referent, String key, String name, ReferenceQueue referenceQueue) { super(checkNotNull(referent, "referent"), checkNotNull(referenceQueue, "referenceQueue")); this.key = checkNotNull(key, "key"); this.name = checkNotNull(name, "name"); } } public void watch(Object watchedReference, String referenceName) { checkNotNull(watchedReference, "watchReference"); checkNotNull(referenceName, "referenceName"); if(debuggerControl.isDebuggerAttached()) { return; } final long watchStartNanoTime = System.nanoTime(); String key = UUID.randomUUID().toString(); retainedKeys.add(key); final KeyedWeakReference reference = new KeyedWeakReference(watchedReference, key, referenceName, queue); watchExecutor.execute() } } 

假设我有一个活动,我希望LeakCanary观看一个对象

SampleActivity.java

 public class SampleActivity extends Activity implements View.OnClickListener { ImageView level001, level002; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.choose_level); level001 = (ImageView) findViewById(R.id.level001); level002 = (ImageView) findViewById(R.id.level002); // Do all kinds of function // How do I use LeakCanary to watch these objects ? } } 

现在我如何使用LeakCanary来查看哪个对象导致内存泄漏。 感谢您的帮助和帮助。

    关于泄漏金丝雀的好处是它的自动化程度。 默认情况下,它已“监视”未正确GCed的活动。 因此,开箱即用,如果有任何活动泄露,您应该收到通知。

    在我的项目中,我在Application上添加了一个额外的方法,如下所示:

     public class ExampleApplication extends Application { public static ExampleApplication instance; private RefWatcher refWatcher; @Override public void onCreate() { super.onCreate(); instance = this; refWatcher = LeakCanary.install(this); } public void mustDie(Object object) { if (refWatcher != null) { refWatcher.watch(object); } } } 

    所以垃圾收集和内存泄漏和金丝雀的重要事情是知道应该收集什么东西并要求观看该项目。

    例如,我们使用带有以下代码的“基本片段”:

     @Override public void onDestroy() { super.onDestroy(); ExampleApplication.instance.mustDie(this); } 

    这样LeakCanary就会试图检查是否有任何碎片泄漏内存。

    因此,对于您在应用程序上进一步实现,您可以/应该在任务或实例上知道它应该是垃圾收集但您认为它可能不是,并且您不确定在哪里,您也可以调用它: ExampleApplication.instance.mustDie(object);

    然后你必须运行应用程序并旋转设备并强制泄漏发生,因此泄漏金丝雀可以抓取/分析堆栈跟踪并为您提供有关如何修复它的重要信息。

    我希望它有所帮助。

    我在应用程序中使用过

     import android.content.Context; import android.support.multidex.MultiDex; import android.support.multidex.MultiDexApplication; import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.RefWatcher; import school.my.com.school.BuildConfig; public class AppController extends MultiDexApplication { private RefWatcher refWatcher; public static RefWatcher getRefWatcher(Context context) { AppController application = (AppController) context.getApplicationContext(); return application.refWatcher; } @Override public void onCreate() { super.onCreate(); if(BuildConfig.DEBUG) refWatcher = LeakCanary.install(this); } } 

    您可以在此处使用Application代替MultiDexApplication

    关于如何使用LeakCanary,我有同样的问题。 我只是想看一个如何启动它并看到我泄漏对象的第一条路径的基本示例。

    如何使用LeakCanary

    以下是LeakCanary如何工作的基本示例:

    如何使用LeakCanary (4分13秒)

    我必须克服的一个问题是弄清楚我必须以常规运行模式启动应用程序而不是调试模式。 我还必须偏离基本指令并设置我的应用程序级build.gradle文件,如下所示:

     dependencies { debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4' releaseImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4' } 

    我认为debugImplementation对我不起作用,因为LeakCanary在调试时忽略了泄漏检测 。 虽然LeakCanary说它提供了它的库的“无操作”版本,但由于调试对我不起作用,我从推荐的com.squareup.leakcanary:leakcanary-android-no-op:1.5.4更改了上面的releaseImplementation com.squareup.leakcanary:leakcanary-android-no-op:1.5.4com.squareup.leakcanary:leakcanary-android:1.5.4

    正如您在video中看到的,我必须处理的另一个问题是提供对LeakCanary的写访问权限。 我向下滑过,看到来自LeakCanary的通知说它无法获得写访问权限( 更多信息 )。 我从未见过许可请求。 所以在一个案例中(未在video中显示),我通过转到设置应用程序,find我的应用程序(而不是LeakCanary安装的名为“Leak”的应用程序),并打开写访问权限,为我的应用程序提供了写访问权限。 在video中,我不需要这样做,因为我通过回复通知给予了许可。 然后在使用我的应用程序时,我会定期检查新通知(通过向下滑动)。 我看到像“XYZActivity泄漏217 KB”这样的消息。 我点了那个,它把我带进了那个Leak应用程序。

    此外,我注意到有时可能需要几分钟才能完成分析并在手机上显示内存泄漏通知 。

    如何使用LeakCanaryvalidation内存泄漏修复

    现在我已经修复了一些内存泄漏,我使用LeakCanary来validation修复。 但是,如果LeakCanary没有报告任何内容,我不一定相信这是因为我的泄漏是固定的。 它可能只是LeakCanary被打破了。

    如何使用LeakCanaryvalidation内存泄漏修复 (16分34秒)

    使用LeakCanaryvalidation内存泄漏的过程:1。使用LeakCanary 2确认内存泄漏。修复内存泄漏并确认LeakCanary报告没有泄漏3.恢复修复并确认LeakCanary再次报告泄漏

    由于LeakCanary在工作时显示非常少的状态信息,因此很难知道它是否正在做任何事情。 这让我觉得我已经修复了内存泄漏,事实上,我没有。 上面的三个步骤是我发现使用LeakCanaryvalidation内存泄漏修复的最佳方法。