1. 程式人生 > >淺談Android記憶體洩漏&&實現殺不死的無介面後臺Service

淺談Android記憶體洩漏&&實現殺不死的無介面後臺Service

以前看大神的部落格,都說沒有碰到過記憶體洩漏或者OOM就不算真正的搞過Android…以前我覺得這事離我還好遠….
沒想到,這次真的是遇上了!!
專案需求是這樣的:app開機自啟,啟動之後app就一直在run,是一直run!(開機自啟,現在大概也就只有在ARM板的原生系統裡實現了…後面的殺不死的後臺Service也是在原生系統上實現的)

遇到的問題:app開機自啟,跑了7,8個小時後app掛掉了
一開始還以為是程式碼有問題,但是程式碼有問題也不可能跑7,8個小時才掛呀…在Google的幫助下,覺得是記憶體洩漏了。好,那就學著用MAT(MemoryAnalyzerTools)去看看到底是哪些資源沒釋放掉唄, MAT的使用可以參照網上大神們的部落格。通過MAT的初步分析,是一個工具類裡面把context宣告成static,並且將MainActivity#this賦給了這個static變數。由於app裡需要對SQLite進行頻繁的操作(線上程裡while(true)去讀,不要問為什麼用while(true),這是前面的人寫的邏輯,我負責填坑),所以必須要有context物件,然後在

胡凱大神部落格裡找到了答案
部落格截圖
好,那就將MainActivity Context改成getApplicationContext…..

還有一個需要修改的地方,由於需要頻繁的操作SQLite所以cursor必須得保證釋放掉,之前的程式碼是直接呼叫cursor#close方法去釋放資源,現在改成在finally程式碼塊裡去呼叫crusor#close,這他媽還不能釋放?!

改完覺得沒啥問題了,讓app再跑7,8小時…………..FU**還是掛掉了

這下懵逼了,只好求教公司的大神了,大神說app能跑7,8個小時,那程式碼肯定是沒問題的,大神最後的建議就是在頻繁操作SQLite的地方加上sleep,釋放掉CPU佔用….好,改程式碼…果然,app不掛了…..

當然,加sleep不是上上策,因為根本沒有找到問題的所在。然後我在另外一塊ARM板上跑沒有加sleep的程式碼,竟然跑了幾天都不掛…..那麼是板子的效能問題?無奈專案太趕,這個問題就用加sleep解決了…

關於Android的記憶體洩漏,還想說的是,在程式碼裡還是儘量少用static,因為釋放不了……

好像很多同學都會碰到這種需求:做一個沒有介面的app(或者service)在後臺一直跑
這種需求,可以很明確的說,現在只有在原生的Android系統裡可以實現。因為現在的手機廠商肯定不會讓開發者這樣搞,不然我們的手機還能用嗎?

所謂的沒有介面,其實是不使用或者不顯示Activity(至少我是這樣做的)。真正的無介面,我覺得只要是在Android上跑的app都不可能(有大神實現了的求指教哇)。

我是這樣實現的:app獲取開機廣播(這個也是隻有在原生Android系統裡才能實現),然後startService開啟一個IntentService。這樣的話,雖然有MainActivity但是我們沒有對它有任何的處理和顯示,也就是說把MainActivity架空了,在IntentService裡重寫onStartCommand方法
這裡寫圖片描述

這段程式碼就實現了將IntentService變成了前臺程序,在通知欄裡會有app的圖標出現,這樣就實現了無介面的後臺service……..當然,再次宣告,這隻能在原生的Android系統裡實現……