摘要:導致了當旋轉屏幕時,無法被回收,而造成內存泄露。但是,她卻會造成嚴重的內存泄露。參考內存泄露問題的整理內存泄露使用中可能引發的內存泄漏介紹了內存泄露有關的解決辦法,下一篇總結遇到時的解決之道。
面試的時候經常會被問道內存泄露優化,和碰到OOM該怎么出來,今天就做個總結。
為什么會內存泄露?根本原因就是一個永遠不會被使用的對象,因為一些引用沒有斷開,沒有滿足GC條件,導致不會被回收,這就造成了內存泄露。比如在Activity中注冊了一個廣播接收器,但是在頁面關閉的時候沒有進行unRegister,就會出現內存溢出的現象。如果我們的java運行很久,而這種內存泄露不斷的發生,最后就沒內存可用了,最終就是我們常看到的OOM錯誤。
如何來解決內存泄露 持有Context引用造成的泄露在Android應用程序中通常可以使用兩種Context對象:Activity和Application。當類或方法需要Context對象的時候常見的做法是使用第一個作為Context參數。這樣就意味著View對象對整個activity保持引用,因此也就保持對activty的所有的引用。
假設一個場景,當應用程序有個比較大的bitmap類型的圖片,每次旋轉是都重新加載圖片所用的時間較多。為了提高屏幕旋轉是Activity的創建速度,最簡單的方法時將這個Bitmap對象使用static修飾。
當一個Drawable綁定在View上,實際上這個View對象就會成為這份Drawable的一個callback成員變量。而靜態變量的生命周期要長于Activity。導致了當旋轉屏幕時,Activity無法被回收,而造成內存泄露。
解決的方法:
使用Application對象,這個對象會隨著應用程序的存在而存在,而不依賴于activity的生命周期。如果打算對context對象進行長期的引用,一定要記住用application對象
總結:避免context泄露:
盡量使用Application的context類型。
對Context的引用不要超過它本身的生命周期,慎重的對Context使用“static”關鍵字。Context里如果有線程,一定要在onDestroy()里及時停掉。
Handler造成的內存泄露public class SampleActivity extends Activity { private final Handler mLeakyHandler = new Handler() { @Override public void handleMessage(Message msg) { // ... } } }
在使用handler時,這時一段很常見的代碼。但是,她卻會造成嚴重的內存泄露。
假設當Handler中有延遲的的任務或是等待執行的任務隊列過長,由于消息持有對handler的引用,而handler又持有對其外部類的潛在引用,這條引用關系會一直保持到消息得到處理,而導致了activity無法被垃圾回收器回收,而導致了內存泄露。
在java里,非靜態內部類 和 匿名類 都會潛在的引用它們所屬的外部類。但是,靜態內部類卻不會
解決方法:
可以把handler類放在多帶帶的類文件中,或者使用靜態內部類便可以避免泄露。
如果想在handler內部去調用所在的Activity,那么可以在handler內部使用弱引用的方式去指向所在Activity.使用Static + WeakReference的方式來達到斷開Handler與Activity之間存在引用關系的目的。
Bitmap沒有及時回收造成的內存泄露Bitmap對象不在使用時調用recycle()釋放內存。2.3以后的bitmap應該是不需要手動recycle了,內存已經在java層了
資源對象沒關造成的內存泄露資源性對象比如(Cursor,File文件等)往往都用了一些緩沖,我們在不使用的時候,應該及時關閉它們,以便它們的緩沖及時回收內存。它們的緩沖不僅存在于 java虛擬機內,還存在于java虛擬機外。如果我們僅僅是把它的引用設置為null,而不關閉它們,往往會造成內存泄漏。因為有些資源性對象,比如 SQLiteCursor(在析構函數finalize(),如果我們沒有關閉它,它自己會調close()關閉),如果我們沒有關閉它,系統在回收它時也會關閉它,但是這樣的效率太低了。因此對于資源性對象在不使用的時候,應該調用它的close()函數,將其關閉掉,然后才置為null.在我們的程序退出時一定要確保我們的資源性對象已經關閉。
構造Adapter時,沒有使用緩存的convertView初始時ListView會從BaseAdapter中根據當前的屏幕布局實例化一定數量的view對象,同時ListView會將這些view對象 緩存起來。
當向上滾動ListView時,原先位于最上面的list item的view對象會被回收,然后被用來構造新出現的最下面的list item。
這個構造過程就是由getView()方法完成的,getView()的第二個形參View convertView就是被緩存起來的list item的view對象(初始化時緩存中沒有view對象則convertView是null)。
在Android程序里面存在很多需要register與unregister的監聽器,我們需要確保及時unregister監聽器。
緩存容器中的內存泄露我們通常把一些對象的引用加入到了集合容器(比如ArrayList)中,當我們不需要該對象時,
并沒有把它的引用從集合中清理掉,這樣這個集合就會越來越大。如果這個集合是static的話,那情況就更嚴重了。
所以要在退出程序之前,將集合里的東西clear,然后置為null,再退出程序。
當我們不要使用WebView對象時,應該調用它的destory()函數來銷毀它,并釋放其占用的內存,否則其占用的內存長期也不能被回收,從而造成內存泄露。
解決方法:
為webView開啟另外一個進程,通過AIDL與主線程進行通信,WebView所在的進程可以根據業務的需要選擇合適的時機進行銷毀,從而達到內存的完整釋放。
參考:
Andriod 內存泄露問題的整理
Android_內存泄露
Handler使用中可能引發的內存泄漏
介紹了內存泄露有關的解決辦法,下一篇總結遇到OOM時的解決之道。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65606.html
摘要:另一種方式就是是一個簡單的,方便的內存檢測工具,可以輕易的發現內存問題,還會生成更加簡單清晰的報告。是一個開源的檢測內存泄露的庫。 在開發Android應用的過程中如果需要處理圖片或者大量數據的時候,就有可能會遇到OOM(java.lang.OutOfMemoryError),一般出現最多的是在創建Bitmap上,也有可能是在內存中處理了大量的數據上。出現OOM應用會直接崩潰,即使沒有...
閱讀 3720·2023-04-25 17:45
閱讀 3431·2021-09-04 16:40
閱讀 1002·2019-08-30 13:54
閱讀 2131·2019-08-29 12:59
閱讀 1400·2019-08-26 12:11
閱讀 3280·2019-08-23 15:17
閱讀 1523·2019-08-23 12:07
閱讀 3882·2019-08-22 18:00