什么是LowMemoryKiller 策略
在Android中,當運行的App被移動到后臺之后篙贸,為了保證下次啟動的速度君珠,會將它移動到Cached的狀態(tài)。這個時候哆料,該App的進程依然存在缸剪,但組建可能已經(jīng)被銷毀(組件不占用內(nèi)存)。這個時候用戶再啟動的速度就比較快东亦,人稱:熱啟動杏节。如果該App的進程已經(jīng)不存在了,重新啟動又需要做很多初始化的工作典阵,就會耗費多一些的時間奋渔,人稱:冷啟動。為了有更好的體驗壮啊,當然盡可能提高App的存活幾率嫉鲸。
LowMemoryKiller 策略就是指那些被退出到后臺的App,并不是不會被清理掉的歹啼,指是可能沒有持有任何組件玄渗,不占用CPU資源,少量占用內(nèi)存空間狸眼。當系統(tǒng)認為內(nèi)存空間不同時藤树,會根據(jù) LRU List 的列表來進行有先后順序的清理工作,回收一些內(nèi)存空間份企,供新啟動的程序使用也榄。
小知識:在adb中查看內(nèi)存狀況
- 查看系統(tǒng)整體內(nèi)存使用狀況
adb shell dumpsys meminfo
可以看到系統(tǒng)中運行的全部進程所占用的內(nèi)存空間。
也能看到哪些App處于 Foreground狀態(tài)司志,哪些處于Cached 狀態(tài)甜紫。
如何進行內(nèi)存優(yōu)化
基于 LowMemoryKiller 策略,那么骂远,為了讓我們的App盡可能地存活下來囚霸,不被系統(tǒng)殺死。那就有兩種方法:
- 提高進程優(yōu)先級
- 降低內(nèi)存占用
提高進程優(yōu)先級激才,不在此文學習范圍拓型。我們就說說降低內(nèi)存占用额嘿。
降低了內(nèi)存占用,也就是相當于降低被回收的幾率劣挫,但這是一個內(nèi)存優(yōu)化方案册养,并不能作為一個App后臺保活的機制(因為即使內(nèi)存優(yōu)化的很低了压固,系統(tǒng)內(nèi)存很小的時候球拦,仍然會被回收,只是降低幾率)帐我。
怎么做坎炼?
如果在App中可以監(jiān)聽自己處于內(nèi)存管理中的什么狀態(tài),我們就可以在適當?shù)臅r機拦键,做一些優(yōu)化工作(比如在后臺的時候回收一些需要顯示的組件)谣光。釋放一些不需要持有的內(nèi)存占用,來達到降低內(nèi)存占用的目的芬为。
onTrimMemory 方法
Android 4.0 之后 官方提供了一個 API萄金,主要作用是提示開發(fā)者在系統(tǒng)內(nèi)存不足時,通過釋放一些不需要的內(nèi)存資源碳柱,從而避免被系統(tǒng)殺掉捡絮。
onTrimMemory回調(diào)
在Android4.0之后,任何實現(xiàn)了 ComponentCallbacks2 接口的類都可以重寫實現(xiàn)這個回調(diào)方法莲镣。
主要作用就是告知App當前處于系統(tǒng)內(nèi)存回收的不同階段的時機福稳,在這些時機下進行自身的內(nèi)存釋放,以避免被系統(tǒng)直接殺掉瑞侮,從而提高下次用戶啟動應用的速度的圆,提高應用的用戶體驗。
onTrimMemory 會回調(diào)一個level參數(shù)半火,分別對應的含義是:
- TRIM_MEMORY_UI_HIDDEN
表示 App 目前所有的 UI 界面都被隱藏越妈,最常見的就是 點擊了 Home鍵 或者 Back鍵后的狀態(tài),App被移到后臺不可見了钮糖,這時候應該釋放一些UI資源梅掠。
這個等級比較常見
下面三個等級是當App正在運行時可能的回調(diào)參數(shù):
- TRIM_MRMORY_RUNNING_MODERATE
表示 App目前正常運行,并且不會被殺掉店归,但是系統(tǒng)的可用內(nèi)存已經(jīng)有點低了阎抒,系統(tǒng)可能會開始根據(jù) LRU list 來殺掉進程了。
- TRIM_MEMORY_RUNNING_LOW
表示 App 目前正常運行消痛,并且不會被殺掉且叁,但是系統(tǒng)的可用內(nèi)存已經(jīng)非常低了。
- TRIM_MEMORY_RUNNING_CRITCAL
表示 App 目前正常運行秩伞,但是系統(tǒng)已經(jīng)開始根據(jù) LUR list 殺掉大部分緩存的進程了逞带。這個時候欺矫,我們應當盡可能地去釋放任何不必要的資源,否則系統(tǒng)可能會繼續(xù)殺掉緩存中的進程(有可能會殺掉一些本來應當保持運行的進程展氓,比如后臺運行的 service)
下面三個等級是當App正在處于Cached狀態(tài)時可能的回調(diào)參數(shù)
- TRIM_MEMORY_BACKGROUND
表示 App目前處于后臺穆趴,同時系統(tǒng)可用內(nèi)存已經(jīng)很低了,準備開始根據(jù)LRU list來清理內(nèi)存带饱,App目前在LRU list比較靠后的地方毡代,暫時不會被殺掉阅羹。
- TRIM_MEMORY_MODERATE
表示 App目前處于后臺勺疼,同時系統(tǒng)可用內(nèi)存已經(jīng)很低了,已經(jīng)開始根據(jù)LRU list來清理內(nèi)存捏鱼, App目前在 LRU lits 的中間位置执庐,如果系統(tǒng)可用內(nèi)存仍然不夠的話,App就有被系統(tǒng)殺掉的風險导梆。
- TRIM_MEMORY_COMPLETE
表示 App目前處于后臺轨淌,同時系統(tǒng)可用內(nèi)存已經(jīng)極低,并且處于 LRU list 靠前的位置看尼,App隨時都有可能被殺掉递鹉,應當盡可能地釋放不必要的資源。
狀態(tài)可以分類三類
- UI 置于后臺: TRIM_MEMORY_UI_HIDDEN
- App正在前臺運行狀態(tài):TRIM_MEMORY_RUNNING_...
- App正在后臺狀態(tài)藏斩,處于Cached狀態(tài):TRIM_MEMORY_...
這三類中躏结,一般只需要關(guān)心當App處于Cached狀態(tài)下的情況,因為系統(tǒng)是不會殺掉一個正在處于前臺運行的App的(但有可能會有OOM的情況)狰域,但是有可能App的后臺運行服務有被殺掉的風險媳拴。
當在Cached狀態(tài)下時,當收到TRIM_MEMORY_... 時兆览,就需要進行處理了屈溉,就算App處在靠后位置(COMPLETE),但是如果系統(tǒng)殺掉了LRU list前面的App后抬探,內(nèi)存仍然不夠的話子巾,也是會進一步殺掉更多的進程。也就是說小压,是有一種可能线梗,會從 TRIM_MEMORY_BACKGROUND 瞬間變成 TRIM_MEMORY_COMPLETE 狀態(tài)的。所以场航,App要盡可能完整地處理每一個狀態(tài)缠导,然后做好回收內(nèi)存的工作。
哪些組件可以實現(xiàn)onTrimMemory回調(diào)
- Application
- Activity
- Fragment
- Service
- ContentProvider
onTrimMemory 回調(diào)中可以釋放哪些資源溉痢?
我們在寫App 的時候就以應該清楚僻造,App哪些東西是需要常駐內(nèi)存的憋他,哪些東西是伴隨界面生命周期而存在的。
一般來說髓削,可以釋放的資源有:
- 緩存:包括一些文件竹挡、圖片緩存的,用戶正常使用的時候這些緩存可以提高用戶體驗立膛,但是當應用UI不存在的時候(又處在低內(nèi)存的境地下)揪罕,這些緩存就可以被清楚以期減少內(nèi)存占用空間。比如:第三方圖片庫的緩存
- 一些動態(tài)生成動態(tài)添加的View:動態(tài)生成或者動態(tài)添加的View或者少數(shù)情況下才會用到的View宝泵,就可以被釋放掉好啰,下次使用的時候再進行動態(tài)生成或添加就可以了。
- ?
onTrimMemory 與 onStop 有什么區(qū)別儿奶?
既然需要釋放資源框往,那我直接在 onStop的時候做不就好了?
onTrimMemory() 方法中的 TRIM_MEMORY_UI_HIDDEN 回調(diào)只有當App的所有UI組件全部不可見的時候才會觸發(fā)闯捎,跟onStop() 還是有很大區(qū)別的椰弊。因為 onStop() 方法只是當一個 Activity 完全不可見時就會調(diào)用,比如說打開了App中的另一個Activity瓤鼻。
因此秉版,我們可以在 onStop() 方法中去釋放一些Activity相關(guān)的資源,比如 取消網(wǎng)絡連接或者注銷廣播接收器等等茬祷,但是像UI相關(guān)的資源清焕,建議是在 onTrimMemory(TRIM_MEMORY_UI_HIDDEN)回調(diào)時才去釋放,這樣才可以保證用戶從后一個Activity返回前一個Activity時不需要重新加載界面資源牲迫,從而提升響應速度耐朴。
注意: onTrimMemory的 TRIM_MEMORY_UI_HIDDEN 等級是在 onStop 方法之前調(diào)用的。
為什么還有一個 onLowMemory
onTrimMemory() 是Android 4.0 以后才增加 的API盹憎。所以筛峭,為了兼容低版本的設(shè)備,可以監(jiān)聽 onLowMemory() 方法陪每,它等同于 onTrimMemory(TRIM_MEMORY_COMPLETE) 的回調(diào)影晓,也就是最緊急的情況了。
已發(fā)布至 我說的這句話是謊話