自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android應(yīng)用內(nèi)存泄露分析、改善經(jīng)驗總結(jié)

移動開發(fā) Android
通過這幾天對好幾個應(yīng)用的內(nèi)存泄露檢測和改善,從結(jié)果來看我分析和改善內(nèi)存泄露的方法是對的,這個過程并不復(fù)雜,所以可以梳理總結(jié)出來作為分享。

前言

通過這幾天對好幾個應(yīng)用的內(nèi)存泄露檢測和改善,效果明顯:

  • 完全退出應(yīng)用時,手動觸發(fā)GC,從原來占有內(nèi)存100多M降到低于20M;
  • 手動觸發(fā)GC后,通過adb shell dumpsys meminfo packagename -d查看Activity和View的數(shù)量也趨近于0了(沒有做到歸零是因為SDK中存在內(nèi)存泄露,需要中間層去處理);
  • 發(fā)現(xiàn)了一個SDK中的內(nèi)存泄露(Android InputMethodManager 導(dǎo)致的內(nèi)存泄露及解決方案);
  • 發(fā)現(xiàn)一個MTK Webview的內(nèi)存泄露(org.chromium.android_webview.AwPasswordHandler.java中private static AwPasswordHandler sInstance = null導(dǎo)致的內(nèi)存泄露)。

從結(jié)果來看我分析和改善內(nèi)存泄露的方法是對的,這個過程并不復(fù)雜,所以可以梳理總結(jié)出來作為分享。

原則

對于性能問題,分析和改善有必要遵循以下原則:

  • 一切看數(shù)據(jù)說話,不能跟著感覺走,感覺哪有問題就去改,很有可能會適得其反;
  • 性能優(yōu)化是一個持續(xù)的過程,需要不斷地改善,不要想著一氣呵成;
  • 對于性能問題,不一定必須要改善,受限于架構(gòu)或者其它原因某些問題可能會很難改善,必須要先保證能用,再才考慮好用。
  • 改善后一定要驗證,任何一個地方的改動都需要驗證,避免因為改善性能問題導(dǎo)致其它的問題。

步驟

下面是我在針對內(nèi)存泄露這個性能問題上的解決步驟:

優(yōu)先處理常見的內(nèi)存泄露問題

首先解決常見的內(nèi)存泄露問題,這個過程可以借助Android Studio的Analyze-Inspect Code對代碼做靜態(tài)分析,常見的內(nèi)存泄露問題有:

  • 非靜態(tài)內(nèi)部類導(dǎo)致的內(nèi)存泄露,比如Handler,解決方法是將內(nèi)部類寫成靜態(tài)內(nèi)部類,在靜態(tài)內(nèi)部類中使用軟引用/弱引用持有外部類的實例,eg:
  1. static class ExerciseHandler extends Handler{ 
  2.  
  3.           private SoftReference<ExerciseActivity> exerciseActivitySoftReference = null
  4.  
  5.   
  6.  
  7.           public ExerciseHandler(ExerciseActivity exerciseActivity){ 
  8.  
  9.               exerciseActivitySoftReference = new SoftReference<ExerciseActivity>(exerciseActivity); 
  10.  
  11.           } 
  12.  
  13.   
  14.  
  15.           @Override 
  16.  
  17.           public void handleMessage(Message msg) { 
  18.  
  19.               ExerciseActivity exerciseActivity = exerciseActivitySoftReference.get(); 
  20.  
  21.               if(null != exerciseActivity){ 
  22.  
  23.                   super.handleMessage(msg); 
  24.  
  25.                   switch (msg.what) { 
  26.  
  27.                       case MSG_XX: 
  28.  
  29.                           exerciseActivity.***; 
  30.  
  31.                           break; 
  32.  
  33.                       default
  34.  
  35.                           break; 
  36.  
  37.                   } 
  38.  
  39.               } 
  40.  
  41.           } 
  42.  
  43.       }  
  • IO操作后,沒有關(guān)閉文件導(dǎo)致的內(nèi)存泄露,比如Cursor、FileInputStream、FileOutputStream使用完后沒有關(guān)閉,這種問題在Android Studio 2.0中能夠通過靜態(tài)代碼分析檢查出來,直接改善就可以了;
  • 自定義View中使用TypedArray后,沒有recycle,這種問題也可以在Android Studio 2.0中能夠通過靜態(tài)代碼分析檢查出來,直接改善就可以了;
  • 某些地方使用了四大組件的context,在離開這些組件后仍然持有其context導(dǎo)致的內(nèi)存泄露,這種問題屬于共識,在編寫代碼的過程中就應(yīng)該按照規(guī)則來,使用Application的Context就可以解決這類內(nèi)存泄露的問題了,至于什么情況下應(yīng)該使用四大組件的Context,什么時候應(yīng)該使用Application的context可以參見下表: 

 

 

application使用場景 

application使用場景

備注:大家注意看到有一些NO上添加了一些數(shù)字,其實這些從能力上來說是YES,但是為什么說是NO呢?下面一個一個解釋:

1、數(shù)字1:啟動Activity在這些類中是可以的,但是需要創(chuàng)建一個新的task,一般情況不推薦;

2、數(shù)字2:在這些類中去layout inflate是合法的,但是會使用系統(tǒng)默認(rèn)的主題樣式,如果你自定義了某些樣式可能不會被使用;

3、數(shù)字3:在Receiver為null時允許,在4.2或以上的版本中,用于獲取黏性廣播的當(dāng)前值。(可以無視);

4、ContentProvider、BroadcastReceiver之所以在上述表格中,是因為在其內(nèi)部方法中都有一個context用于使用。

還有一種不屬于內(nèi)存泄露,但在分析內(nèi)存泄露的問題時應(yīng)該一并解決:同一個APP,將圖片放在不同的drawable文件夾下,在相同的設(shè)備上占用的內(nèi)存情況不一樣,具體可以參見:關(guān)于Android中圖片大小、內(nèi)存占用與drawable文件夾關(guān)系的研究與分析。解決這個問題遵循以下原則就可以了:1、UI只提供一套高分辨率的圖,圖片建議放在drawable-xxhdpi文件夾下(放在xxxhdpi或者更高分辨率的文件夾下沒有必要,權(quán)衡利弊,照顧主流設(shè)備即可),這樣在低分辨率設(shè)備中圖片的大小只是壓縮,不會存在內(nèi)存增大的情況;2、涉及到桌面插件或者不需要縮放的圖片,放在drawable-nodpi文件夾下,這個文件夾下的圖片在任何設(shè)備上都是不會縮放的。

通過工具檢查程序運行后的內(nèi)存泄露

通過上面的步驟,應(yīng)用中的大部分內(nèi)存泄露問題都能夠得到解決,還有一些內(nèi)存泄露,需要運行程序,分析運行后的內(nèi)存快照來解決,比如注冊之后沒有反注冊、類中的靜態(tài)成員變量導(dǎo)致的內(nèi)存泄露、SDK中的內(nèi)存泄露等。解決這類問題可以分兩步進(jìn)行:

  • 通過內(nèi)存泄露檢測工具先定位是哪有問題,內(nèi)存泄露的檢測有兩種比較便捷的方式:1、一種是使用開源項目Leakcanary,需要添加到代碼中,運行后生成分析結(jié)果;2、另一種方式是使用adb shell dumpsys meminfo packagename -d命令,在進(jìn)入一個界面之前查看一遍Activity和View的數(shù)量,在退出這個界面之后再查看一遍Activity和View的數(shù)量,對比進(jìn)入前和進(jìn)入后Activity和View數(shù)量的變化情況,如果有差異,則說明存在內(nèi)存泄露(在使用命令查看Activity和View的數(shù)量之前,記得手動觸發(fā)GC)。 

 

 

 

備注:在Android Studio中,可以通過如下方式獲取當(dāng)前選中進(jìn)程的內(nèi)存信息: 

 

 

 

  • 然后通過MAT取程序運行時的內(nèi)存快照做詳細(xì)分析,對于MAT的使用,網(wǎng)上有很多優(yōu)質(zhì)的文章,比如:Android 性能優(yōu)化之使用MAT分析內(nèi)存泄露問題,在使用MAT前,有必要知道這幾點:1、 不要指望MAT明確告訴你哪里存在內(nèi)存泄露,這需要你根據(jù)上一步驟首先定位到可能存在內(nèi)存泄露的類,然后借助MAT確認(rèn)是否真的存在內(nèi)存泄露,具體哪個地方存在內(nèi)存泄露;2、借助Retained Size分析某一個類及與之相關(guān)的實例所消耗的內(nèi)存,如果這個類的Retained Size比較大,優(yōu)先分析;3、檢查某個類是否存在內(nèi)存泄露時,排除其軟/弱/虛引用,右鍵某個類→Merge Shortest Paths to GC Roots→exclude all phantom/weak/soft etc.references。

驗證改善效果

根據(jù)個人經(jīng)驗,我一般是這樣驗證改善效果的,運行程序,各個功能跑一遍,確保沒有改出問題,完全退出程序,手動觸發(fā)GC,然后通過adb shell dumpsys meminfo packagename -d查看Activivites和Views的數(shù)量是否趨近于0;如果不是0,通過Leakcanary檢查可能存在內(nèi)存泄露的地方,繼續(xù)通過MAT分析,周而復(fù)始,改善到自己滿意為止。

推薦閱讀

  • Speed up your app
  • Android 性能優(yōu)化之使用MAT分析內(nèi)存泄露問題
責(zé)任編輯:龐桂玉 來源: 安卓開發(fā)精選
相關(guān)推薦

2010-01-27 18:12:14

Android dia

2010-01-25 14:25:33

Android Int

2009-11-17 11:24:00

PHP應(yīng)用技巧

2010-01-26 13:28:11

Android開發(fā)要點

2009-12-31 10:21:53

Silverlight

2010-05-06 17:30:56

Oracle查詢語句

2009-10-15 09:27:00

2010-01-06 15:52:11

軟交換技術(shù)

2009-10-27 10:46:27

ADSL接入技術(shù)

2010-02-02 15:44:18

C++遍歷集合

2009-08-19 09:24:43

AJAX引擎經(jīng)驗總結(jié)

2009-09-29 16:32:11

OJB Hiberna

2010-01-25 13:37:07

Android傳感器

2009-09-16 17:13:54

學(xué)習(xí)Linq

2010-04-28 17:14:38

Oracle EXPL

2009-10-23 09:43:44

光纖接入網(wǎng)

2010-09-13 10:52:37

CSS定位

2017-01-05 16:29:00

2011-07-21 13:40:17

java

2009-08-13 18:13:27

C#學(xué)習(xí)經(jīng)驗
點贊
收藏

51CTO技術(shù)棧公眾號