- LeakCanary简介
-
LeakCanary是Square公司开源的一个检测内存的泄露的函数库,可以方便地和你的项目进行集成,在Debug版本中监控Activity、Fragment等的内存泄露
-
LeakCanary集成到项目中之后,在检测到内存泄露时,会发送消息到系统通知栏。点击后打开名称DisplayLeakActivity的页面,并显示泄露的跟踪信息,Logcat上面也会有对应的日志输出
- 内存泄漏简介
-
为什么会产生内存泄漏?
当一个对象不需要使用本该回收时,有另外一个正在使用的对象持有它的引用,从而导致它不能回收停留在堆内存中,这就产生了内存泄漏 -
内存泄露对程序产生的影响?
内存泄漏是造成应用程序OOM的主要原因之一。Android系统为每个应用程序分配有限的内存,当应用中内存泄漏较多时,就难免会导致应用所需要的内存超出系统分配限额,从而导致OOM应用Crash
- LeakCanary接入
-
我们以LeakCanaryTest项目进行演示如何在项目中接入LeakCanary,项目目录如下:
1522222494(1).png
整个结构非常的简单如上图所示
-
在主项目main模块的build.gradle文件中添加LeakCanary相关依赖 -/main/build.gradle文件
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
// 添加leakcanary相关的依赖
// 在release版本中,使用的是LeakCanary的no-op版本,也就是没有实际代码和操作的Wrapper版本
// 只包含LeakCanary和RefWatcher类的空实现,这样不会对生成的APK包体积和应用性能造成影响
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
}
- 初始化LeakCanary在主项目main模块的QApplication的onCreate()方法中初始化LeakCanary
leakcanary.com.leakcanarytest.FFApplication文件
public class FFApplication extends Application
{
@Override
public void onCreate()
{
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this))
{
return;
}
LeakCanary.install(this);
}
}
这样我们就完成了一个项目的LeankCanary的简单接入
- LeakCanary检测
下面我们以常见内存—单例造成的内存泄露为例进行实践
- 单例内存泄露模拟
LeakcanaryTest\app\src\main\java\leakcanary\com\leakcanarytest\TestManager.java
public class TestManager
{
//单例静态特性使得单例的生命周期和应用的生命周期一样长
private static TestManager instance;
private Context context;
/**:
* 传入的是Application的Context,则生命周期和单例生命周期一样长;
* 传入的是Activity的Context,由于该Context和Activity的生命周期一样长,当Activity退出的时候它的内存不会被回收,因为单例对象持有它的引用;
*/
private TestManager(Context context) {
this.context = context;
}
public static TestManager getInstance(Context context) {
if (instance == null) {
instance = new TestManager(context);
}
return instance;
}
}
5.检测消息通知
-
运行App到LeakCanaryActivit页面并退出,在检测到内存泄露的时候,会发送消息到系统通知栏如下图所示
1522223392(1).png
1522223450(1).png
-
对于开发人员这时可以很清晰的看到内存泄露了并及时修复代码!
- LeakCanary原理
- 源码里面的watch()函数会为被监控的对象创建一个KeyedWeakReference弱引用对象,是WeakReference对的子类,增加了键值对信息,后面会根据指定的键key找到弱引用对象
- 在后台线程中,检查KeyedWeakReference弱引用是否已经被清除。如果没有,则触发一次GC,GC之后,如果弱引用对象依然存在,说明发生了内存泄露
- 对于项目的好处
- 对于开发人员来说,可以优化app代码,减少内存泄漏和bug,有利于后期维护
- 对于测试人员,完善后的APP,可以大大减轻测试的难度和强度

网友评论