GitHub 地址
LeakCanary 是用于检测内存泄漏的工具,它相对与MAT十分易用。并且十分直观,它会在通知栏中给出泄漏信息,这些信息可以分享,还可以dump出来。
内存泄漏
那么什么是内存泄漏呢?在之前的内存优化的博客中已经提到过内存泄漏,这里再做下回顾:
在Java中每个对象都有自己的有限的生命周期,一超过这个生命周期就会被垃圾回收器标记回收,但是还有一种情况就是它在超过生命周期的时候它的引用还被其他对象引用,这时候它就不能被垃圾回收器正常回收,并腾出空间。就导致了内存泄漏。
总之一句话,在应该被回收的时候,却没有被回收就会导致内存泄漏。内存泄漏的结果就是有限的内存被耗尽,最终导致OOM。
那么怎么将LeakCanary呢?下面将会对其一步一步介绍:
添加依赖
dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2' testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2' }
|
这里有三个依赖分别对应的是debug版本,release版本,测试版本的对应依赖,之所以分成这么多个是因为需要在每个不同的版本表现出不同的行为。
在项目中引入
创建MyApplication类,在该类中创建getRefWatcher静态方法,通过该静态方法提供LeakCanary.install(this)返回的RefWatcher对象,这个对象用于内存泄漏溢出检测。
public class MyApplication extends Application{ public static RefWatcher getRefWatcher(Context context) { MyApplication application = (MyApplication) context .getApplicationContext(); return application.refWatcher; } private RefWatcher refWatcher; @Override public void onCreate() { super.onCreate(); refWatcher = LeakCanary.install(this); } }
|
将MyApplication设置为当前应用。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.idealist.testleakcandy" >
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:name=".MyApplication" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
</manifest>
|
点击按钮的时候启动AsyncTask,在AsyncTask中睡眠20秒,由于AsyncTask持有外部类MainActivity的引用所以当按钮按下的时候,如果转屏就会发生内存溢出。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RefWatcher refWatcher = MyApplication.getRefWatcher(this); refWatcher.watch(this); mButton = (Button) findViewById(R.id.buttons); mButton.setOnClickListener(this); }
@Override public void onClick(View v) { startAsyncTask(); }
private void startAsyncTask() { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { SystemClock.sleep(20000); return null; } }.execute(); } }
|
运行结果如下:
较好的博客:
http://blog.csdn.net/watermusicyes/article/details/46333925
http://www.jianshu.com/p/0049e9b344b0
http://www.tuicool.com/articles/RvURJv