Android內存泄漏終極解決方法介紹
一、概述
在 Android內存泄漏終極解決篇(上)中我們介紹瞭如何檢查一個App是否存在內存泄漏的問題,本篇將總結典型的內存泄漏的代碼,並給出對應的解決方案。內存泄漏的主要問題可以分爲以下幾種類型:
靜態變量引起的內存泄漏 非靜態內部類引起的內存泄漏 資源未關閉引起的內存泄漏
二、靜態變量引起的內存泄漏
在java中靜態變量的生命週期是在類加載時開始,類卸載時結束。換句話說,在android中其生命週期是在進程啓動時開始,進程死亡時結束。所以在程序的運行期間,如果進程沒有被殺死,靜態變量就會一直存在,不會被回收掉。如果靜態變量強引用了某個Activity中變量,那麼這個Activity就同樣也不會被釋放,即便是該Activity執行了onDestroy(不要將執行onDestroy和被回收劃等號)。這類問題的解決方案爲:1.尋找與該靜態變量生命週期差不多的替代對象。2.若找不到,將強引用方式改成弱引用。比較典型的例子如下:
單例引起的Context內存泄漏
public class IMManager { private Context context; private static IMManager mInstance; public static IMManager getInstance(Context context) { if (mInstance == null) { synchronized (s) { if (mInstance == null) mInstance = new IMManager(context); } } return mInstance; } private IMManager(Context context) { ext = context; }}
當調用getInstance時,如果傳入的context是Activity的context。只要這個單例沒有被釋放,這個Activity也不會被釋放。
解決方案
傳入Application的context,因爲Application的context的生命週期比Activity長,可以理解爲Application的context與單例的生命週期一樣長,傳入它是最合適的。
public class IMManager { private Context context; private static IMManager mInstance; public static IMManager getInstance(Context context) { if (mInstance == null) { synchronized (s) { if (mInstance == null) //將傳入的`context轉換成Application的context mInstance = new IMManager(pplicationContext()); } } return mInstance; } private IMManager(Context context) { ext = context; }}
三、非靜態內部類引起的內存泄漏
在java中,創建一個非靜態的內部類實例,就會引用它的外圍實例。如果這個非靜態內部類實例做了一些耗時的操作,就會造成外圍對象不會被回收,從而導致內存泄漏。這類問題的解決方案爲:1.將內部類變成靜態內部類 2.如果有強引用Activity中的屬性,則將該屬性的引用方式改爲弱引用。3.在業務允許的情況下,當Activity執行onDestory時,結束這些耗時任務。
內部線程造成的內存泄漏
public class LeakAty extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { eate(savedInstanceState); setContentView(_leak); test(); } public void test() { //匿名內部類會引用其外圍實例,所以會導致內存泄漏 new Thread(new Runnable() { @Override public void run() { while (true) { try { p(1000); } catch (InterruptedException e) { tStackTrace(); } } } })t(); } }
解決方案
將非靜態匿名內部類修改爲靜態匿名內部類
public class LeakAty extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { eate(savedInstanceState); setContentView(_leak); test(); } //加上static,變成靜態匿名內部類 public static void test() { new Thread(new Runnable() { @Override public void run() { while (true) { try { p(1000); } catch (InterruptedException e) { tStackTrace(); } } } })t(); }}
Handler引起的內存泄漏
public class LeakAty extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { eate(savedInstanceState); setContentView(_leak); fetchData(); } private Handler mHandler = new Handler() { public void handleMessage(age msg) { switch () { case 0: // 刷新數據 break; default: break; } }; }; private void fetchData() { //獲取數據 EmptyMessage(0); }}
mHandler 爲匿名內部類實例,會引用外圍對象,如果該Handler在Activity退出時依然還有消息需要處理,那麼這個Activity就不會被回收。
解決方案
public class LeakAty extends Activity { private TextView tvResu< private MyHandler handler; @Override protected void onCreate(Bundle savedInstanceState) { eate(savedInstanceState); setContentView(_leak); tvResult = (TextView) findViewById(sult); handler = new MyHandler(this); fetchData(); } //第一步,將Handler改成靜態內部類。 private static class MyHandler extends Handler { //第二步,將需要引用Activity的地方,改成弱引用。 private WeakReferenceatyInstance; public MyHandler(LeakAty aty) { nstance = new WeakReference(aty); } @Override public void handleMessage(Message msg) { leMessage(msg); LeakAty aty = atyInstance == null ? null : (); //如果Activity被釋放回收了,則不處理這些消息 if (aty == null||nishing()) { return; } ext("fetch data success"); } } private void fetchData() { // 獲取數據 EmptyMessage(0); } @Override protected void onDestroy() { //第三步,在Activity退出的時候移除回調 stroy(); veCallbacksAndMessages(null); }}
四、資源未關閉引起的內存泄漏
當使用了BraodcastReceiver、Cursor、Bitmap等資源時,當不需要使用時,需要及時釋放掉,若沒有釋放,則會引起內存泄漏。
綜上所述,內存泄漏的主要情況爲上面的三大類型,最終歸結爲一點,就是資源在不需要的時候沒有被釋放掉。所以在編碼的過程中要注意這些細節,提高程序的性能。
相關文章
-
如何用fuzz技術挖掘Android漏洞 Android漏洞該如何防禦
爲確保事情或工作順利開展,我們需要提前開始方案制定工作,方案是闡明具體行動的時間,地點,目的,預期效果,預算及方法等的企劃案。優秀的方案都具備一些什麼特點呢?以下是小編收集整理的教師讀書活動方案,歡迎大家借鑑與參考,希 -
android5.0系統奔潰解決方法彙總
安卓5.0系統崩潰怎麼辦?小編帶來了android5.0系統奔潰解決方法,爲什麼安卓5.0經常發生應用崩潰、啓動器重繪、延遲的情況呢?如果你想知道原因以及如何解決的`話,就請看下文吧。希望會對大家有所幫助的吧。安裝了Android -
Android編碼的常見錯誤及解決方法分享
一年一度的長跑比賽又開始了,只是這次比賽的規則有些變化,那就是運動員可以自由選擇助手幫助跑步。小兔子聽了很高興,因爲它和袋鼠媽媽是好朋友,而袋鼠媽媽跑步的速度可是一流的。 小兔子找到袋鼠媽媽說:袋鼠媽媽,長跑比賽 -
audiodg.exe進程佔用內存高的解決方法
在win8系統下,用戶在啓用遊戲或聊天軟件時,卻發現系統沒有聲音的問題,用戶在對任務管理器進行查看時,卻發現音頻設備圖形隔離進程佔用大量內存,有時甚至會佔用到100%,造成應用程序時區響應的問題,對於這一問題我們如何解決呢 -
Thinkpad筆記本開機顯示Tointerrruptnormalstartup解決方法
Thinkpad筆記本開機顯示To interrrupt normal startup的解決方法1、先等待5-6分鐘,如果系統又恢復了正常,說明可能是系統硬盤或者風扇區出了問題;2、假如過了5-6分鐘依然沒有反應,則可嘗試先拆掉筆記本電池在裝上;3、或 -
Win10系統提示Officebackgroundtaskhandler.exe彈窗問題的解決方
win10系統經常彈出名稱爲“”的.彈窗怎麼辦?如何解決?針對這一問題,本文就爲大家圖文介紹Win10系統彈窗問題的解決方法,有興趣的朋友們就來了解下吧!前陣子有不少朋友反映,自己 Windows 10 屏幕總是會彈出一個神祕窗口,眼疾 -
android SDk中常用的java包功能介紹
在平平淡淡的學習、工作、生活中,大家都跟作文打過交道吧,藉助作文人們可以實現文化交流的目的。相信許多人會覺得作文很難寫吧,以下是小編整理的快樂六一的作文4篇,歡迎大家借鑑與參考,希望對大家有所幫助。快樂六一的作 -
解決PHP的failed opening required問題的方法
人要想學習一點東西,就應該先學會謙遜。以下是小編爲大家搜索整理的解決PHP的failed opening required問題的方法,希望對大家有所幫助!更多精彩內容請及時關注我們應屆畢業生考試網!環境:WIN2003+IIS6+PHP5本機,2003下IIS -
關於Android中EditText光標在4.0中的bug及解決方法
本文分析了Android中EditText光標在4.0中的bug及解決方法。分享給大家供大家參考,具體如下:一、問題:不知道爲什麼,我的EditText的在我自己的手機中出現的時候,他的`光標就變得沒有了,我開始還以爲是光標不見了,後面我修改了 -
Windows10 彈出defender的解決方法
Windows10 defender提示“病毒和間諜軟件定義更新失敗”怎麼辦?Windows defender是系統自帶的殺毒程序,最近一位Windows10用戶在更新Windows defender時,系統提示“病毒和間諜軟件定義更新失敗”,這是怎麼回事呢?出現這種