內(nèi)存泄漏:
指程序在申請內(nèi)存后 ,無法釋放已經(jīng)申請的內(nèi)存空間熊响,一次內(nèi)存泄漏可以忽略,但內(nèi)存泄漏堆積后果很嚴(yán)重诗赌,無論多少內(nèi)存汗茄,都會被占光
內(nèi)存泄露危害:
1.內(nèi)存泄露最終會導(dǎo)致內(nèi)存溢出(OOM)
2.導(dǎo)致程序卡頓,應(yīng)用程序莫名退出
內(nèi)存泄露檢測工具
- Memory Monitor(不能精準(zhǔn)的定位問題)
- MAT工具 (操作復(fù)雜铭若,學(xué)習(xí)成本高)
- 還有許多就不一一列舉了
Android中常見的內(nèi)存泄露(歡迎指證與添加)
大圖片也能造成OOM
hangdler造成的內(nèi)存泄露解決辦法
當(dāng)Activity退出時(shí)消息隊(duì)列中還有未處理的消息或者正在處理的消息
而消息隊(duì)列中的Messager持有handler實(shí)例的引用洪碳, handler又持有activity的引用,所以導(dǎo)致Activity的內(nèi)存資源無法及時(shí)回收叼屠,引發(fā)內(nèi)存泄露
解決辦法:
1.使用弱引用
2.使用靜態(tài)handler內(nèi)部類
3.在onDestory()方法中調(diào)用removeCallbacksAndMessagers(null);
單例造成的內(nèi)存泄露解決辦法
原因:單例的靜態(tài)特性 使得單例的生命周期和應(yīng)用的生命周期一樣長瞳腌,這就說明如果一個(gè)對象已經(jīng)不需要使用了,而單例對象還持有該對象的引用镜雨,那么這個(gè)對象不能正成┦蹋回收,就會導(dǎo)致內(nèi)存泄露
解決辦法:如果此時(shí)傳入的是 Activity 的 Context,當(dāng)這個(gè) Context 所對應(yīng)的 Activity 退出時(shí)挑宠,由于該 Context 的引用被單例對象所持有菲盾,其生命周期等于整個(gè)應(yīng)用程序的生命周期,所以當(dāng)前 Activity 退出時(shí)它的內(nèi)存并不會被回收各淀,這就造成泄漏了
所以如果此時(shí)傳入的是 Application 的 Context懒鉴,因?yàn)?Application 的生命周期就是整個(gè)應(yīng)用的生命周期,所以這沒有任何問題碎浇。
非靜態(tài)內(nèi)部類創(chuàng)建實(shí)例造成的內(nèi)存泄露
將該內(nèi)部類設(shè)為靜態(tài)內(nèi)部類或?qū)⒃搩?nèi)部類抽取出來封裝成一個(gè)單例临谱,如果需要使用Context,請使用ApplicationContext
線程造成的內(nèi)存泄露
異步任務(wù)和Runnable都是一個(gè)匿名內(nèi)部類奴璃,因此它們對當(dāng)前Activity都有一個(gè)隱式引用悉默。如果Activity在銷毀之前,任務(wù)還未完成苟穆,
那么將導(dǎo)致Activity的內(nèi)存資源無法回收麦牺,造成內(nèi)存泄漏
解決辦法
正確的做法還是使用靜態(tài)內(nèi)部類的方式
資源沒有關(guān)閉造成的內(nèi)存泄露
如數(shù)據(jù)庫 流
LeakCanary介紹
這個(gè)才是今天的正題
LeakCanary使用示例
??參考LeakCanary官方示例 https://github.com/square/leakcanary:
首先我們需要在應(yīng)用的 build.gradle 中,添加依賴:
<pre><code>
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.2'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.2
</code></pre>
LeakCanary依賴添加后鞭缭,我們添加一個(gè)Application類
1.創(chuàng)建個(gè)MyApplication類
<pre><code>
public class MyApplication extends Application {
private RefWatcher refWatcher;
@Override
public void onCreate() {
super.onCreate();
refWatcher = LeakCanary.install(this);
}
}
</pre></code>
2.在AndroidManifest.xml文件中去配置這個(gè)application
android:name=".MyApplication"
3.LeakCanary的配置就已經(jīng)完成了剖膳,
然后運(yùn)行應(yīng)用程序除了會安裝自己的App外還會安裝leaks這個(gè)東西
4.完(萬)事具備,只欠東方 下面我就舉個(gè)內(nèi)存泄露的例子
<pre><code>
private void initView() {
Button tv = (Button) findViewById(R.id.tv);
tv.setText("dsafsdfadsfdsafsa");
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AsyncTaskTest();
finish();
}
}
);
}
public void AsyncTaskTest() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(20000000);
return null;
}
}.execute();
}
</pre></code>