• Android内存泄露自动检测神器LeakCanary


    经典的面试题:

    a、怎样在coding过程中避免内存泄露?

    b、怎样检测内存泄露?

    这两个问题我想大部分Android 职位面试时都会被问到吧。

            怎样避免就不赘述了,网上很多答案。

           工具呢,当然也有很多,比如DDMS、MAT等,但是怎样在我们编码过程中植入内存检测代码,让我们程序在开发调试阶段就能发现内存泄露呢?好了,现在该大名鼎鼎的LeakCanary出场了,它是Square公司的一个内存探测开源项目。下面就介绍下怎样使用.


    1、配置gradle依赖:    

    1. debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'  
    2. releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'  

    2、初始化Watcher

    1. package com.micky.leakcanarysamples;;  
    2.   
    3. import android.app.Application;  
    4.   
    5. import com.squareup.leakcanary.LeakCanary;  
    6. import com.squareup.leakcanary.RefWatcher;  
    7.   
    8. /** 
    9.  * @Project LeakCanaryTest 
    10.  * @Packate com.micky.leakcanarysamples; 
    11.  * @Description 
    12.  * @Author Micky Liu 
    13.  * @Email mickyliu@126.com 
    14.  * @Date 2016-01-04 10:32 
    15.  * @Version 1.0 
    16.  */  
    17. public class BaseApplication extends Application {  
    18.   
    19.     private static BaseApplication instance;  
    20.   
    21.     private RefWatcher mRefWatcher;  
    22.   
    23.     @Override  
    24.     public void onCreate() {  
    25.         super.onCreate();  
    26.         instance = this;  
    27.         mRefWatcher = Constants.DEBUG ?  LeakCanary.install(this) : RefWatcher.DISABLED;  
    28.     }  
    29.   
    30.     public static BaseApplication getInstance() {  
    31.         return instance;  
    32.     }  
    33.   
    34.     public static RefWatcher getRefWatcher() {  
    35.         return getInstance().mRefWatcher;  
    36.     }  
    37. }  


    3、在Activity或Fragment中添加检测

    1. package com.micky.leakcanarysamples;  
    2.   
    3. import android.app.Activity;  
    4. import android.support.v7.app.AppCompatActivity;  
    5.   
    6. /** 
    7.  * @Project LeakCanaryTest 
    8.  * @Packate com.micky.leakcanarysamples; 
    9.  * @Description 
    10.  * @Author Micky Liu 
    11.  * @Email mickyliu@126.com 
    12.  * @Date 2016-01-04 10:39 
    13.  * @Version 1.0 
    14.  */  
    15. public class BaseActivity extends AppCompatActivity {  
    16.   
    17.     @Override  
    18.     protected void onDestroy() {  
    19.         super.onDestroy();  
    20.         BaseApplication.getRefWatcher().watch(this);  
    21.     }  
    22. }  

    4、测试
    1. package com.micky.leakcanarysamples;;  
    2.   
    3. import android.os.Bundle;  
    4. import android.os.Handler;  
    5.   
    6. /** 
    7.  * @Project LeakCanaryTest 
    8.  * @Packate com.micky.leakcanarysamples; 
    9.  * @Description 
    10.  * @Author Micky Liu 
    11.  * @Email mickyliu@126.com 
    12.  * @Date 2016-01-04 10:29 
    13.  * @Version 1.0 
    14.  */  
    15. public class TestActivity extends BaseActivity {  
    16.   
    17.     private final Handler mHandler = new Handler();  
    18.   
    19.     @Override  
    20.     protected void onCreate(Bundle savedInstanceState) {  
    21.         super.onCreate(savedInstanceState);  
    22.         //模拟内存泄露  
    23.         mHandler.postDelayed(new Runnable() {  
    24.             @Override  
    25.             public void run() {  
    26.   
    27.             }  
    28.         }, 3 * 60 * 1000);  
    29.         finish();  
    30.     }  
    31. }  


    5、测试结果

    a、Toast显示(大概10秒左右显示)



    b、通知显示



    c、桌面自动添加的图表



    d、内存泄露列表



    e、内存泄露详细



    LogCat可以看到日志日下(hprof文件可以用MAT打开进行分析):

    1. 01-04 11:49:41.815 12967-13004/com.micky.leakcanarysamples I/dalvikvm: hprof: dumping heap strings to "/storage/emulated/0/Download/leakcanary/suspected_leak_heapdump.hprof".  
    2. 01-04 11:49:42.020 12967-13004/com.micky.leakcanarysamples I/dalvikvm: hprof: heap dump completed (28850KB)  


    查看自动生成的AndroidManifest文件,LeakCanarySamples/app/build/intermediates/manifests/full/debug/AndroidManifest.xml

    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     package="com.micky.leakcanarysamples"  
    4.     android:versionCode="1"  
    5.     android:versionName="1.0" >  
    6.   
    7.     <uses-sdk  
    8.         android:minSdkVersion="10"  
    9.         android:targetSdkVersion="23" />  
    10.   
    11.     <!-- To store the heap dumps and leak analysis results. -->  
    12.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
    13.   
    14.     <android:uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />  
    15.   
    16.     <application  
    17.         android:name="com.micky.leakcanarysamples.BaseApplication"  
    18.         android:allowBackup="true"  
    19.         android:icon="@mipmap/ic_launcher"  
    20.         android:label="@string/app_name"  
    21.         android:supportsRtl="true"  
    22.         android:theme="@style/AppTheme" >  
    23.         <activity  
    24.             android:name="com.micky.leakcanarysamples.MainActivity"  
    25.             android:label="@string/app_name"  
    26.             android:theme="@style/AppTheme.NoActionBar" >  
    27.             <intent-filter>  
    28.                 <action android:name="android.intent.action.MAIN" />  
    29.   
    30.                 <category android:name="android.intent.category.LAUNCHER" />  
    31.             </intent-filter>  
    32.         </activity>  
    33.         <activity android:name="com.micky.leakcanarysamples.TestActivity" />  
    34.   
    35.         <service  
    36.             android:name="com.squareup.leakcanary.internal.HeapAnalyzerService"  
    37.             android:enabled="false"  
    38.             android:process=":leakcanary" />  
    39.         <service  
    40.             android:name="com.squareup.leakcanary.DisplayLeakService"  
    41.             android:enabled="false" />  
    42.   
    43.         <activity  
    44.             android:name="com.squareup.leakcanary.internal.DisplayLeakActivity"  
    45.             android:enabled="false"  
    46.             android:icon="@drawable/__leak_canary_icon"  
    47.             android:label="@string/__leak_canary_display_activity_label"  
    48.             android:taskAffinity="com.squareup.leakcanary"  
    49.             android:theme="@style/__LeakCanary.Base" >  
    50.             <intent-filter>  
    51.                 <action android:name="android.intent.action.MAIN" />  
    52.   
    53.                 <category android:name="android.intent.category.LAUNCHER" />  
    54.             </intent-filter>  
    55.         </activity>  
    56.     </application>  
    57.   
    58. </manifest>  

    如上所示LeakCanary给我们自动添加了两个Service和一个Activity,并添加了对SD卡的读写权限


    It 's so simple.

    注: 

    1、如果在Release模式下请使用RefWatcher.DISABLED

     2、在Activity或Fragment 的 Destroy方法中添加检测(很好理解,就是判断一个Activity或Fragment想要被销毁的时候,是否还有其他对象持有其引用导致Activity或Fragment不能被回收,从而导致内存泄露)


    源码地址:https://github.com/mickyliu945/LeakCanarySample   点击打开链接

  • 相关阅读:
    pickle模块的基本使用
    python selenium 开发环境配置
    ubuntu ftp服务器搭建
    再探VIM配置
    counting elements--codility
    Time complexity--codility
    Arrays--codility
    Iterations --codility
    adobe reader DC 字体设置
    按位操作
  • 原文地址:https://www.cnblogs.com/ldq2016/p/6636427.html
Copyright © 2020-2023  润新知