今天楼主遇到引用LeakCanary时代码跟官网一样但是就不弹出来。楼主新建项目就可以正常使用。楼主郁闷半天,现在终于整出来了。

楼主主工程app引用module为thirdParty,本想为了整洁三方的都扔进这个thirdParty 结果导致了这个没弄出来。

1.写一个application :

  1. <application
  2. android:name=".BaseApplication"
  1. public class BaseApplication extends Application {
  2. private static BaseApplication app;
  3. private DaoMaster daoMaster;
  4. private DaoSession daoSession;
  5. private SQLiteDatabase db;
  6. private String TAG="BaseApplication";
  7. @Override
  8. public void onCreate() {
  9. super.onCreate();
  10. Log.i(TAG, "onCreate: ");
  11. app = this;
  12. LeakCanary.install(this);
  13. initDB();
  14. }

2.写一段让程序泄露的代码:

  1. void startAsyncTask() {
  2. // This async task is an anonymous class and therefore has a hidden reference to the outer
  3. // class MainActivity. If the activity gets destroyed before the task finishes (e.g. rotation),
  4. // the activity instance will leak.
  5. new AsyncTask<Void, Void, Void>() {
  6. @Override
  7. protected Void doInBackground(Void... params) {
  8. // Do some slow work in background
  9. SystemClock.sleep(200000);
  10. return null;
  11. }
  12. }.execute();
  13. Toast.makeText(this, "请关闭这个A完成泄露", Toast.LENGTH_SHORT).show();
  14. }

3.添加build.gradle 由于我把所有的依赖都写在的thirdParty这个lib中

仔细观察一下这个引用不太一样:

我们平时引用都是:

  1. compile 'com.github.lzyzsd.randomcolor:library:1.0.0'

而LeakCanary的引用是:

  1. debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'

后来我又写到了主app中 结果可以使用了。。。

查了一下他们的含义:

Compile

compile是对所有的build type以及favlors都会参与编译并且打包到最终的apk文件中。

Provided

Provided是对所有的build type以及favlors只在编译时使用,类似eclipse中的external-libs,只参与编译,不打包到最终apk。

APK

只会打包到apk文件中,而不参与编译,所以不能再代码中直接调用jar中的类或方法,否则在编译时会报错

Test compile

Test compile 仅仅是针对单元测试代码的编译编译以及最终打包测试apk时有效,而对正常的debug或者release apk包不起作用。

Debug compile

Debug compile 仅仅针对debug模式的编译和最终的debug apk打包。

Release compile

Release compile 仅仅针对Release 模式的编译和最终的Release apk打包。

还不太清楚为啥。。。但是给大家提个醒。

下面转一个非常好的文章:http://droidyue.com/blog/2016/03/28/android-leakcanary/

懒人可以看我下面的转载

Android内存泄漏检测利器:LeakCanary

MAR 28TH, 2016

是什么?

一言以蔽之:LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具

为什么需要LeakCanary?

因为它简单,易于发现问题,人人可参与。

  • 简单:只需设置一段代码即可,打开应用运行一下就能够发现内存泄露。而MAT分析需要Heap Dump,获取文件,手动分析等多个步骤。
  • 易于发现问题:在手机端即可查看问题即引用关系,而MAT则需要你分析,找到Path To GC Roots等关系。
  • 人人可参与:开发人员,测试测试,产品经理基本上只要会用App就有可能发现问题。而传统的MAT方式,只有部分开发者才有精力和能力实施。

如何集成

尽量在app下的build.gradle中加入以下依赖

1
2
3
4
5
 dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' // or 1.4-beta1
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1
}

在Application中加入类似如下的代码

1
2
3
4
5
6
7
public class ExampleApplication extends Application {

  @Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}
}

到这里你就可以检测到Activity的内容泄露了。其实现原理是设置Application的ActivityLifecycleCallbacks方法监控所有Activity的生命周期回调。内部实现代码为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public final class ActivityRefWatcher {
private final ActivityLifecycleCallbacks lifecycleCallbacks = new ActivityLifecycleCallbacks() {
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
} public void onActivityStarted(Activity activity) {
} public void onActivityResumed(Activity activity) {
} public void onActivityPaused(Activity activity) {
} public void onActivityStopped(Activity activity) {
} public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
} public void onActivityDestroyed(Activity activity) {
ActivityRefWatcher.this.onActivityDestroyed(activity);
}
};
private final Application application;
private final RefWatcher refWatcher; public static void installOnIcsPlus(Application application, RefWatcher refWatcher) {
if(VERSION.SDK_INT >= 14) {
ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);
activityRefWatcher.watchActivities();
}
}
....
}

想要检测更多?

首先我们需要获得一个RefWatcher,用来后续监控可能发生泄漏的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyApplication extends Application {
private static RefWatcher sRefWatcher; @Override
public void onCreate() {
super.onCreate();
sRefWatcher = LeakCanary.install(this);
} public static RefWatcher getRefWatcher() {
return sRefWatcher;
}
}

监控某个可能存在内存泄露的对象

1
MyApplication.getRefWatcher().watch(sLeaky);

哪些需要进行监控

默认情况下,是对Activity进行了检测。另一个需要监控的重要对象就是Fragment实例。因为它和Activity实例一样可能持有大量的视图以及视图需要的资源(比如Bitmap)即在Fragment onDestroy方法中加入如下实现

1
2
3
4
5
6
7
public class MainFragment extends Fragment {
@Override
public void onDestroy() {
super.onDestroy();
MyApplication.getRefWatcher().watch(this);
}
}

其他也可以监控的对象

  • BroadcastReceiver
  • Service
  • 其他有生命周期的对象
  • 直接间接持有大内存占用的对象(即Retained Heap值比较大的对象)

何时进行监控

首先,我们需要明确什么是内存泄露,简而言之,某个对象在该释放的时候由于被其他对象持有没有被释放,因而造成了内存泄露。

因此,我们监控也需要设置在对象(很快)被释放的时候,如Activity和Fragment的onDestroy方法。

一个错误示例,比如监控一个Activity,放在onCreate就会大错特错了,那么你每次都会收到Activity的泄露通知。

如何解决

常用的解决方法思路如下

  • 尽量使用Application的Context而不是Activity的
  • 使用弱引用或者软引用
  • 手动设置null,解除引用关系
  • 将内部类设置为static,不隐式持有外部的实例
  • 注册与反注册成对出现,在对象合适的生命周期进行反注册操作。
  • 如果没有修改的权限,比如系统或者第三方SDK,可以使用反射进行解决持有关系

加入例外

有些特殊情况,我们需要忽略一些问题,这时候就需要添加例外规则。比如ExampleClass.exampleField会导致内存泄漏,我们想要忽略,如下操作即可。

1
2
3
4
5
6
7
8
9
// ExampleApplication is defined in "Customizing and using the no-op dependency"
public class DebugExampleApplication extends ExampleApplication {
protected RefWatcher installLeakCanary() {
ExcludedRefs excludedRefs = AndroidExcludedRefs.createAppDefaults()
.instanceField("com.example.ExampleClass", "exampleField")
.build();
return LeakCanary.install(this, DisplayLeakService.class, excludedRefs);
}
}

如何实现的

LeakCanary实际上就是在本机上自动做了Heap dump,然后对生成的hprof文件分析,进行结果展示。和手工进行MAT分析步骤基本一致。

如何不影响对外版APK

是的,这个问题确实值得关注,因为LeakCanary确实是影响程序运行的,尤其是heap dump操作,不过好在这件事Square已经考虑了,即在我们增加依赖时

1
2
3
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' // or 1.4-beta1
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1

其中releaseCompile和testCompile这两个的依赖明显不同于debugCompile的依赖。它们的依赖属于NOOP操作。

NOOP,即No Operation Performed,无操作指令。常用的编译器技术会检测无操作指令并出于优化的目的将无操作指令剔除。

因而,只要配置好releaseCompile和testCompile的依赖,就无需担心对外版本的性能问题了。

实践中的问题

  • 如果targetSdkVersion为23,在6.0的机器上会存在问题,卡死,因为LeakCanary并没有很好支持Marshmallow运行时权限,所以始终得不到sd卡权限,进而导致卡死。

注意

  • 目前LeakCanary一次只能报一个泄漏问题,如果存在内存泄漏但不是你的模块,并不能说明这个模块没有问题。建议建议将非本模块的泄漏解决之后,再进行检测。

Anroid中内存泄漏相关文章

使用LeakCanary遇到的问题 就是不弹出来的更多相关文章

  1. Android性能优化之利用LeakCanary检测内存泄漏及解决办法

    前言: 最近公司C轮融资成功了,移动团队准备扩大一下,需要招聘Android开发工程师,陆陆续续面试了几位Android应聘者,面试过程中聊到性能优化中如何避免内存泄漏问题时,很少有人全面的回答上来. ...

  2. Android内存泄漏检测利器:LeakCanary

    Android内存泄漏检测利器:LeakCanary MAR 28TH, 2016 是什么? 一言以蔽之:LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具 为什么需要LeakCanary? ...

  3. LeakCanary,30分钟从入门到精通

    简述 在性能优化中,内存是一个不得不聊的话题:然而内存泄漏,显示已经成为内存优化的一个重量级的方向.当前流行的内存泄漏分析工具中,不得不提的就是LeakCanary框架:这是一个集成方便, 使用便捷, ...

  4. 内存测试——内存泄露工具 LeakCanary

    项目地址 https://github.com/square/leakcanary 接入方法 1. 配置依赖 dependencies { debugCompile 'com.squareup.lea ...

  5. 【android】通过leakCanary找出程序内存泄露点

    背景 内存泄露是咱新手比较头痛的问题,因为它不像崩溃,在开发环境可以根据提示的错误信息排查问题. 你都不知道咱的app是否哪个犄角旮旯藏着一个吞噬内存的黑洞. 排查android 内存泄露比较底层高端 ...

  6. android 内存泄漏检测工具 LeakCanary 泄漏金丝雀

    韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha 313134555@qq.com 内存泄漏检测工具 android 内存泄漏检测工具 ======== 内存泄漏 就是  无用的对 ...

  7. Android内存优化8 内存检测工具2 LeakCanary——直白的展现Android中的内存泄露

    之前碰到的OOM问题,终于很直白的呈现在我的眼前:我尝试了MAT,但是发现不怎么会用.直到今天终于发现了这个新工具: 当我们的App中存在内存泄露时会在通知栏弹出通知: 当点击该通知时,会跳转到具体的 ...

  8. Android内存泄漏排查利器LeakCanary

    开源地址:https://github.com/square/leakcanary 在 build.gralde 里加上依赖, 然后sync 一下, 添加内容如下 dependencies { ... ...

  9. LeakCanary——直白的展现Android中的内存泄露

    之前碰到的OOM问题,终于很直白的呈现在我的眼前:我尝试了MAT,但是发现不怎么会用.直到今天终于发现了这个新工具: 当我们的App中存在内存泄露时会在通知栏弹出通知: 当点击该通知时,会跳转到具体的 ...

随机推荐

  1. 非常全的API接口查询

    http://www.apix.cn/services/category/3 https://www.showapi.com/ https://www.juhe.cn/docs http://deve ...

  2. 最简单的RSA及其几个网站和工具

    最简单的形式 给你公钥和一个密文. flag.enc就是密文,我们用记事本是看不出什么的,其实也不用看,因为后边的解密是直接用脚本读取文件的,只需要知道这是密文. pub.pem就是公钥,用记事本打开 ...

  3. C# 序列化和反序列化 详解

    什么是序列化以及如何实现序列化? 如何将对象数据写入 XML 文件? 如何从 XML 文件读取对象数据? 什么是序列化以及如何实现序列化? 序列化是通过将对象转换为字节流,从而存储对象或将对象传输到内 ...

  4. 深入学习之mysql(五)连接查询

    深入学习Mysql(五)连接查询 1.准备数据库: CREATE DATABASE IF NOT EXISTS `db_book2` DEFAULT CHARACTER SET UTF8; USE ` ...

  5. 观15级K班团队作业有感

    1.指尖加密 特点:通过可移动设备手机参与电脑文件的解密,使加密更加安全. 缺点:跟柯逍老师的想法差不多,UI简陋,操作不是很友好,或许可以加一个帮助文档. 2.youreyes 特点:可以检测路过的 ...

  6. hdu2586&&poj1330 求点间最短距&&最近公共祖先(在线&&离线处理):::可做模板

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  7. java 数据库连接 驱动相关参数

    mysql: driverClass=com.mysql.jdbc.Driver connectionURL=jdbc:mysql://localhost:3306/shiro userId=root ...

  8. mapserver+openlayers实现左键点击查询

    效果图 第一步,配置自己的mapfile,在要查询的图层LAYER对象内加上HEADER,TEMPLATE,FOOTER三个参数,同时,TEMPLATE fooOnlyForWMSGetFeature ...

  9. bzoj2338数矩形(rectangle)

    数矩形(rectangle) 计算几何 把所有点两两连线,把这些线按长度排序,再按中点排序 能组成矩形的线一定是连续的 最坏就是所有点围成一个圆,交于圆心 复杂度O(可以过) 要用叉积,不然会被卡精 ...

  10. codechef May Challenge 2016 FORESTGA: Forest Gathering 二分

    Description All submissions for this problem are available. Read problems statements in Mandarin Chi ...