LeakCanary使用指南(1)

引言

  还在为不会使用MAT而烦恼吗?还在对着MAT工具解析出的hprof图拼命找内存泄露的源头吗?放弃挣扎吧,少年。Android Studio时代,我们使用LeakCanary——傻瓜式的内存泄露检测工具。如果你想了解引发Java内存泄露的深层原因,请移步Java 内存从分配到泄露 了解相关基础知识。

简介

  LeakCanary产自著名的Square公司,就是那个生产了网络请求框架OkHttp、Retrofit、图片加载框架Picasso的那个。LeakCanary可以让你的App在Debug模式下发生内存泄露时主动弹框提醒,而在Release模式下什么都不影响。

官网链接

  Github上LeakCanary的源码首页A memory leak detection library for Android and Java。如果你是个良好的英文阅读者,那么无需往下看,首页上有你想要的一切。

快速集成

  第一步:在build.gradle中添加如下依赖:

dependencies {
   debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
   releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
   testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
 }

  第二步:在自己的Application(假设名为ExampleApplication)中添加如下代码:

public class ExampleApplication extends Application {

  @Override public void onCreate() {
    super.onCreate();
    if (LeakCanary.isInAnalyzerProcess(this)) {
      // This process is dedicated to LeakCanary for heap analysis.
      // You should not init your app in this process.
      return;
    }
    LeakCanary.install(this);
    // Normal app init code...
  }
}

  到这里其实可以检测到Activity的内存泄露了,原理后面再说。以Debug模式运行你的App,你可以看到,你App的图标后面跟着一个Leaks图标,如下图;而如果你以Release模式运行,则没有这个图标。
  

LeakCanary图标

测试使用

  假装你是测试人员,你开始各种点击App,进行测试。然后你有幸看到这样一个弹框,如下图。
  

LeakCanary弹框

  你很好奇,然后点击了弹框中间那个图标,于是手机屏幕的左上角出现了你App的图标,再下拉点击那个图标,或者从桌面上LeakCanary图标(跟在你App的图标屁股后面那个)点进去,你看到下图。点击+号可以展开,点击-号收起。
  

LeakCanary泄露详情

  内存泄露往往发生在,生命周期较长的对象,直接或间接持有了生命周期较短的对象的强引用,导致了生命周期较短的对象不能及时释放
  上图已经够傻瓜式了,第一行表示生命周期较长的那个对象,图中是AliPayModel这个类;第二行表示生命周期长的那个持有了一个什么样的引用,图中是mActivity;第三行表示生命周期较短的那个对象,图中是SelectPayTypeActivity。
  回去查看源码,发现AliPayModel是个单例,在SelectPayTypeActivity中以AliPayModel.getInstance(this).XXX()的方式调用单例中的XXX()方法。于是AliPayModel通过mActivity持有了SelectPayTypeActivity.this的引用。SelectPayTypeActivity本来应该在用户退出这个页面和进入其他Activity(尤其是其他Activity层级较深时)时释放掉,但是单例的生命周期贯穿整个App,AliPayModel一直引用着SelectPayTypeActivity,导致SelectPayTypeActivity不能及时释放,引发内存泄露。

public class AliPayModel extends BasePayModel {
    private Activity mActivity;
    private AliPayModel() {}
    private static AliPayModel instance = new AliPayModel();
    public static AliPayModel getInstance(Activity tag) {
        instance.mActivity = tag;
        return instance;
    }

  找到了原因,解决方法也呼之欲出。要么AliPayModel这个业务类不要定义成单例,要么mActivity由强引用改成软引用或者弱引用。Java的强、软、弱、虚四种引用的区别不在本文的讨论范围。

发现开源组件中的内存泄露

  用上述方法,可以检测出各种各样的内存泄露,包括:WebView导致的内存泄露、资源未关闭导致的内存泄露、非静态匿名内部类导致的内存泄露、Handler导致的内存泄露等等。
  请看下图,每次选择图片、上传头像时都会引发0.96M的内存泄露!
  

开源组件泄露详情

  再按图索骥,发现罪魁祸首是将一个Activity定义为static。表示不是很能理解这种神代码。最让人心中万马奔腾的是,它竟然有2600多个star!在这个项目的Issues中很多人反映内存占用大、容易OOM、卡顿等,但是没有人从技术层面去查找和分析原因,更遑论去阅读源码,都是直接拿来就用!
  如果你正打算替换该图片选择框架,不妨参考拍照/图片选择–裁剪–压缩 一条龙这个项目。
  
GalleryFinal神代码
  

总结

  经过简单的配置,我们非常快速地发现了自己项目中存在的内存泄露的代码,并且无意中发现了开源组件中的严重内存泄露问题。下次面试被问到内存泄露检测工具,请不要只会习惯性地说MAT。
  但以上就是LeakCanary的全部吗?远远不是!除了Activity,我们还可以监视哪些对象?我们可以不监视哪些Activity(怎样添加例外)?怎样定制自己的LeakCanary?
  Github上每个国外的牛逼项目,都会在README或者Wiki中详细介绍它的使用、配置、实现原理等等,或者附上博客、网站的外链。如果你不习惯在官网获得第一手资料,那么本文的续篇LeakCanary使用指南(2)值得你期待!

LeakCanary是一个用于检测Android应用程序内存泄漏的开源库。它可以帮助开发者在开发和测试过程中快速发现和解决内存泄漏问题。 要使用LeakCanary,您需要在您的Android项目中添加以下依赖项(在您的build.gradle文件的dependencies部分): ``` debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.x.x' releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:2.x.x' ``` 接下来,在您的Application类中初始化LeakCanary: ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); if (LeakCanary.isInAnalyzerProcess(this)) { // 这个进程是用于LeakCanary分析的,不执行LeakCanary的初始化操作 return; } LeakCanary.install(this); } } ``` LeakCanary会自动检测您的应用程序中的内存泄漏,并在检测到泄漏时提供详细的报告。当您运行应用程序时,如果发现内存泄漏,LeakCanary会在通知栏中显示一个通知,并在您的应用程序退出时显示一个通知。 通过分析LeakCanary提供的报告,您可以确定内存泄漏的原因,并采取相应的措施来解决问题,例如释放对象引用、取消注册监听器等。 请注意,LeakCanary仅在调试构建中生效,不会影响发布版本的性能。因此,在发布应用程序之前,请确保将LeakCanary从releaseImplementation更改为leakcanary-android-no-op。 希望这个简单的介绍对您有帮助!如果您有任何其他问题,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值