0. OnTrimMemory回調(diào)的作用?
OnTrimMemory是Android在4.0之后加入的一個回調(diào)夯接,任何實現(xiàn)了ComponentCallbacks2接口的類都可以重寫實現(xiàn)這個回調(diào)方法.OnTrimMemory的主要作用就是指導(dǎo)應(yīng)用程序在不同的情況下進行自身的內(nèi)存釋放殴蹄,以避免被系統(tǒng)直接殺掉吩屹,提高應(yīng)用程序的用戶體驗.
Android系統(tǒng)會根據(jù)不同等級的內(nèi)存使用情況斋竞,調(diào)用這個函數(shù),并傳入對應(yīng)的等級:
- TRIM_MEMORY_UI_HIDDEN 表示應(yīng)用程序的所有UI界面被隱藏了啥刻,即用戶點擊了Home鍵或者Back鍵導(dǎo)致應(yīng)用的UI界面不可見.這時候應(yīng)該釋放一些資源.
TRIM_MEMORY_UI_HIDDEN這個等級比較常用奸鸯,和下面六個的關(guān)系不是很強,所以單獨說.
下面三個等級是當我們的應(yīng)用程序真正運行時的回調(diào):
- TRIM_MEMORY_RUNNING_MODERATE 表示應(yīng)用程序正常運行可帽,并且不會被殺掉娄涩。但是目前手機的內(nèi)存已經(jīng)有點低了,系統(tǒng)可能會開始根據(jù)LRU緩存規(guī)則來去殺死進程了映跟。
- TRIM_MEMORY_RUNNING_LOW 表示應(yīng)用程序正常運行蓄拣,并且不會被殺掉扬虚。但是目前手機的內(nèi)存已經(jīng)非常低了,我們應(yīng)該去釋放掉一些不必要的資源以提升系統(tǒng)的性能球恤,同時這也會直接影響到我們應(yīng)用程序的性能辜昵。
- TRIM_MEMORY_RUNNING_CRITICAL 表示應(yīng)用程序仍然正常運行,但是系統(tǒng)已經(jīng)根據(jù)LRU緩存規(guī)則殺掉了大部分緩存的進程了碎捺。這個時候我們應(yīng)當盡可能地去釋放任何不必要的資源路鹰,不然的話系統(tǒng)可能會繼續(xù)殺掉所有緩存中的進程,并且開始殺掉一些本來應(yīng)當保持運行的進程收厨,比如說后臺運行的服務(wù)。
當應(yīng)用程序是緩存的优构,則會收到以下幾種類型的回調(diào):
- TRIM_MEMORY_BACKGROUND 表示手機目前內(nèi)存已經(jīng)很低了诵叁,系統(tǒng)準備開始根據(jù)LRU緩存來清理進程。這個時候我們的程序在LRU緩存列表的最近位置钦椭,是不太可能被清理掉的,但這時去釋放掉一些比較容易恢復(fù)的資源能夠讓手機的內(nèi)存變得比較充足,從而讓我們的程序更長時間地保留在緩存當中太示,這樣當用戶返回我們的程序時會感覺非常順暢挽荠,而不是經(jīng)歷了一次重新啟動的過程。
- TRIM_MEMORY_MODERATE 表示手機目前內(nèi)存已經(jīng)很低了德挣,并且我們的程序處于LRU緩存列表的中間位置恭垦,如果手機內(nèi)存還得不到進一步釋放的話,那么我們的程序就有被系統(tǒng)殺掉的風險了格嗅。
- TRIM_MEMORY_COMPLETE 表示手機目前內(nèi)存已經(jīng)很低了番挺,并且我們的程序處于LRU緩存列表的最邊緣位置,系統(tǒng)會最優(yōu)先考慮殺掉我們的應(yīng)用程序屯掖,在這個時候應(yīng)當盡可能地把一切可以釋放的東西都進行釋放玄柏。
1. 哪些組件可以實現(xiàn)OnTrimMemory回調(diào)?
- Application.onTrimMemory()
- Activity.onTrimMemory()
- Fragement.OnTrimMemory()
- Service.onTrimMemory()
- ContentProvider.OnTrimMemory()
2. OnTrimMemory回調(diào)中可以釋放哪些資源贴铜?
通常在架構(gòu)階段就要考慮清楚粪摘,我們有哪些東西是要常駐內(nèi)存的,有哪些是伴隨界面存在的.一般情況下绍坝,有下面幾種資源需要進行釋放:
- 緩存 緩存包括一些文件緩存徘意,圖片緩存等,在用戶正常使用的時候這些緩存很有作用陷嘴,但當你的應(yīng)用程序UI不可見的時候映砖,這些緩存就可以被清除以減少內(nèi)存的使用.比如第三方圖片庫的緩存.
- 一些動態(tài)生成動態(tài)添加的View. 這些動態(tài)生成和添加的View且少數(shù)情況下才使用到的View,這時候可以被釋放灾挨,下次使用的時候再進行動態(tài)生成即可.比如原生桌面中邑退,會在OnTrimMemory的TRIM_MEMORY_MODERATE等級中竹宋,釋放所有AppsCustomizePagedView的資源,來保證在低內(nèi)存的時候地技,桌面不會輕易被殺掉.
2.1 例子:釋放不常用到的View.
代碼出處:Launcher
Launcher.java:
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
mAppsCustomizeTabHost.onTrimMemory();
}
}
AppsCustomizeTabHost.java:
public void onTrimMemory() {
mContent.setVisibility(GONE);
// Clear the widget pages of all their subviews - this will trigger the widget previews
// to delete their bitmaps
mPagedView.clearAllWidgetPages();
}
AppsCustomizePagedView.java:
public void clearAllWidgetPages() {
cancelAllTasks();
int count = getChildCount();
for (int i = 0; i < count; i++) {
View v = getPageAt(i);
if (v instanceof PagedViewGridLayout) {
((PagedViewGridLayout) v).removeAllViewsOnPage();
mDirtyPageContent.set(i, true);
}
}
}
PagedViewGridLayout.java
@Override
public void removeAllViewsOnPage() {
removeAllViews();
mOnLayoutListener = null;
setLayerType(LAYER_TYPE_NONE, null);
}
2.2 例子: 清除緩存
代碼出處:Contact
@Override
public void onTrimMemory(int level) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
// Clear the caches. Note all pending requests will be removed too.
clear();
}
}
public void clear() {
mPendingRequests.clear();
mBitmapHolderCache.evictAll();
mBitmapCache.evictAll();
}
3. OnTrimMemory和onStop的關(guān)系蜈七?
onTrimMemory()方法中的TRIM_MEMORY_UI_HIDDEN回調(diào)只有當我們程序中的所有UI組件全部不可見的時候才會觸發(fā),這和onStop()方法還是有很大區(qū)別的莫矗,因為onStop()方法只是當一個Activity完全不可見的時候就會調(diào)用飒硅,比如說用戶打開了我們程序中的另一個Activity。
因此作谚,我們可以在onStop()方法中去釋放一些Activity相關(guān)的資源三娩,比如說取消網(wǎng)絡(luò)連接或者注銷廣播接收器等,但是像UI相關(guān)的資源應(yīng)該一直要等到onTrimMemory(TRIM_MEMORY_UI_HIDDEN)這個回調(diào)之后才去釋放妹懒,這樣可以保證如果用戶只是從我們程序的一個Activity回到了另外一個Activity雀监,界面相關(guān)的資源都不需要重新加載,從而提升響應(yīng)速度眨唬。
需要注意的是会前,onTrimMemory的TRIM_MEMORY_UI_HIDDEN 等級是在onStop方法之前調(diào)用的.
4. OnTrimMemory和OnLowMemory的關(guān)系?
在引入OnTrimMemory之前都是使用OnLowMemory回調(diào)匾竿,需要知道的是瓦宜,OnLowMemory大概和OnTrimMemory中的TRIM_MEMORY_COMPLETE級別相同,如果你想兼容api<14的機器岭妖,那么可以用OnLowMemory來實現(xiàn)临庇,否則你可以忽略O(shè)nLowMemory,直接使用OnTrimMemory即可.
5. 為什么要調(diào)用OnTrimMemory区转?
盡管系統(tǒng)在內(nèi)存不足的時候殺進程的順序是按照LRU Cache中從低到高來的苔巨,但是它同時也會考慮殺掉那些占用內(nèi)存較高的應(yīng)用來讓系統(tǒng)更快地獲得更多的內(nèi)存。
所以如果你的應(yīng)用占用內(nèi)存較小废离,就可以增加不被殺掉的幾率侄泽,從而快速地恢復(fù)(如果不被殺掉,啟動的時候就是熱啟動蜻韭,否則就是冷啟動悼尾,其速度差在2~3倍)。
所以說在幾個不同的OnTrimMemory回調(diào)中釋放自己的UI資源肖方,可以有效地提高用戶體驗闺魏。
6. 有哪些典型的使用場景?
6.1 常駐內(nèi)存的應(yīng)用
一些常駐內(nèi)存的應(yīng)用俯画,比如Launcher析桥、安全中心、電話等,在用戶使用過要退出的時候泡仗,需要調(diào)用OnTrimMemory來及時釋放用戶使用的時候所產(chǎn)生的多余的內(nèi)存資源:比如動態(tài)生成的View埋虹、圖片緩存、Fragment等娩怎。
6.2 有后臺Service運行的應(yīng)用
這些應(yīng)用不是常駐內(nèi)存的搔课,意味著可以被任務(wù)管理器殺掉,但是在某些場景下用戶不會去殺截亦。
這類應(yīng)用包括:音樂爬泥、下載等。用戶退出UI界面后崩瓤,音樂還在繼續(xù)播放袍啡,下載程序還在運行。這時候音樂應(yīng)該釋放部分UI資源和Cache(目前在播放音樂的時候却桶,音樂應(yīng)用占用將近140m內(nèi)存)葬馋。