Android代碼內(nèi)存優(yōu)化建議-OnTrimMemory優(yōu)化

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)存)葬馋。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市肾扰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蛋逾,老刑警劉巖集晚,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異区匣,居然都是意外死亡偷拔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門亏钩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來莲绰,“玉大人,你說我怎么就攤上這事姑丑「蚯” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵栅哀,是天一觀的道長震肮。 經(jīng)常有香客問我,道長留拾,這世上最難降的妖魔是什么戳晌? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮痴柔,結(jié)果婚禮上沦偎,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好豪嚎,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布搔驼。 她就那樣靜靜地躺著,像睡著了一般疙渣。 火紅的嫁衣襯著肌膚如雪匙奴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天妄荔,我揣著相機與錄音泼菌,去河邊找鬼。 笑死啦租,一個胖子當著我的面吹牛哗伯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播篷角,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼焊刹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了恳蹲?” 一聲冷哼從身側(cè)響起虐块,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘉蕾,沒想到半個月后贺奠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡错忱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年儡率,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片以清。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡儿普,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掷倔,到底是詐尸還是另有隱情眉孩,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布今魔,位于F島的核電站勺像,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏错森。R本人自食惡果不足惜吟宦,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涩维。 院中可真熱鬧殃姓,春花似錦袁波、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至踏幻,卻和暖如春枷颊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背该面。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工夭苗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人隔缀。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓题造,卻偏偏與公主長得像,于是被迫代替她去往敵國和親猾瘸。 傳聞我的和親對象是個殘疾皇子界赔,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容