Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android資訊 >> 從OnTrimMemory角度談Android代碼內存優化

從OnTrimMemory角度談Android代碼內存優化

編輯:Android資訊

OnTrimMemory 回調是 Android 4.0 之後提供的一個API,這個 API 是提供給開發者的,它的主要作用是提示開發者在系統內存不足的時候,通過處理部分資源來釋放內存,從而避免被 Android 系統殺死。這樣應用在下一次啟動的時候,速度就會比較快。
本文通過問答的方式,從各個方面來講解 OnTrimMemory 回調的使用過程和效果。想要開發高性能且用戶體驗良好的 Android 應用,那麼這篇文章你不應該錯過。

相關文章:從Android資源角度談Android代碼內存優化

0. OnTrimMemory回調的作用?

OnTrimMemory是Android在4.0之後加入的一個回調,任何實現了ComponentCallbacks2接口的類都可以重寫實現這個回調方法.OnTrimMemory的主要作用就是 指導應用程序在不同的情況下進行自身的內存釋放,以避免被系統直接殺掉,提高應用程序的用戶體驗.

Android系統會根據不同等級的內存使用情況,調用這個函數,並傳入對應的等級:

  • TRIM_MEMORY_UI_HIDDEN 表示應用程序的 所有UI界面被隱藏了,即用戶點擊了Home鍵或者Back鍵導致應用的UI界面不可見.這時候應該釋放一些資源.TRIM_MEMORY_UI_HIDDEN這個等級比較常用,和下面六個的關系不是很強,所以單獨說.

下面三個等級是當我們的應用程序真正運行時的回調:

  • TRIM_MEMORY_RUNNING_MODERATE 表示應用程序正常運行,並且不會被殺掉。但是目前手機的內存已經有點低了,系統可能會開始根據LRU緩存規則來去殺死進程了。
  • TRIM_MEMORY_RUNNING_LOW 表示應用程序正常運行,並且不會被殺掉。但是目前手機的內存已經非常低了,我們應該去釋放掉一些不必要的資源以提升系統的性能,同時這也會直接影響到我們應用程序的性能。
  • TRIM_MEMORY_RUNNING_CRITICAL 表示應用程序仍然正常運行,但是系統已經根據LRU緩存規則殺掉了大部分緩存的進程了。這個時候我們應當盡可能地去釋放任何不必要的資源,不然的話系統可能會繼續殺掉所有緩存中的進程,並且開始殺掉一些本來應當保持運行的進程,比如說後台運行的服務。

當應用程序是緩存的,則會收到以下幾種類型的回調:

  • TRIM_MEMORY_BACKGROUND 表示手機目前內存已經很低了,系統准備開始根據LRU緩存來清理進程。這個時候我們的程序在LRU緩存列表的最近位置,是不太可能被清理掉的,但這時去釋放掉一些比較容易恢復的資源能夠讓手機的內存變得比較充足,從而讓我們的程序更長時間地保留在緩存當中,這樣當用戶返回我們的程序時會感覺非常順暢,而不是經歷了一次重新啟動的過程。
  • TRIM_MEMORY_MODERATE 表示手機目前內存已經很低了,並且我們的程序處於LRU緩存列表的中間位置,如果手機內存還得不到進一步釋放的話,那麼我們的程序就有被系統殺掉的風險了。
  • TRIM_MEMORY_COMPLETE 表示手機目前內存已經很低了,並且我們的程序處於LRU緩存列表的最邊緣位置,系統會最優先考慮殺掉我們的應用程序,在這個時候應當盡可能地把一切可以釋放的東西都進行釋放。

1. 哪些組件可以實現OnTrimMemory回調?

  • Application.onTrimMemory()
  • Activity.onTrimMemory()
  • Fragement.OnTrimMemory()
  • Service.onTrimMemory()
  • ContentProvider.OnTrimMemory()

2. OnTrimMemory回調中可以釋放哪些資源?

通常在架構階段就要考慮清楚,我們有哪些東西是要常駐內存的,有哪些是伴隨界面存在的.一般情況下,有下面幾種資源需要進行釋放:

  • 緩存 緩存包括一些文件緩存,圖片緩存等,在用戶正常使用的時候這些緩存很有作用,但當你的應用程序UI不可見的時候,這些緩存就可以被清除以減少內存的使用.比如第三方圖片庫的緩存.
  • 一些動態生成動態添加的View. 這些動態生成和添加的View且少數情況下才使用到的View,這時候可以被釋放,下次使用的時候再進行動態生成即可.比如原生桌面中,會在 OnTrimMemory的TRIM_MEMORY_MODERATE等級中,釋放所有AppsCustomizePagedView的資源,來保證在低內存的時候,桌面不會輕易被殺掉.

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的關系?

onTrimMemory()方法中的TRIM_MEMORY_UI_HIDDEN回調只有當我們程序中的所有UI組件全部不可見的時候才會觸發,這和onStop()方法還是有很大區別的,因為onStop()方法只是當一個Activity完全不可見的時候就會調用,比如說用戶打開了我們程序中的另一個Activity。

因此,我們可以在onStop()方法中去釋放一些Activity相關的資源,比如說取消網絡連接或者注銷廣播接收器等,但是像UI相關的資源應該一直要等到onTrimMemory(TRIM_MEMORY_UI_HIDDEN)這個回調之後才去釋放,這樣可以保證如果用戶只是從我們程序的一個Activity回到了另外一個Activity,界面相關的資源都不需要重新加載,從而提升響應速度。

需要注意的是,onTrimMemory的TRIM_MEMORY_UI_HIDDEN 等級是在onStop方法之前調用的.

4. OnTrimMemory和OnLowMemory的關系?

在引入OnTrimMemory之前都是使用OnLowMemory回調,需要知道的是,OnLowMemory大概和 OnTrimMemory中的TRIM_MEMORY_COMPLETE級別相同,如果你想兼容api<14的機器,那麼可以用 OnLowMemory來實現,否則你可以忽略OnLowMemory,直接使用OnTrimMemory即可.

5. 為什麼要調用OnTrimMemory?

盡管系統在內存不足的時候殺進程的順序是按照LRU Cache中從低到高來的,但是它同時也會考慮殺掉那些占用內存較高的應用來讓系統更快地獲得更多的內存。

所以如果你的應用占用內存較小,就可以增加不被殺掉的幾率,從而快速地恢復(如果不被殺掉,啟動的時候就是熱啟動,否則就是冷啟動,其速度差在2~3倍)。

所以說在幾個不同的OnTrimMemory回調中釋放自己的UI資源,可以有效地提高用戶體驗。

6. 有哪些典型的使用場景?

6.1 常駐內存的應用

一些常駐內存的應用,比如Launcher、安全中心、電話等,在用戶使用過要退出的時候,需要調用OnTrimMemory來及時釋放用戶使用的時候所產生的多余的內存資源:比如動態生成的View、圖片緩存、Fragment等。

6.2 有後台Service運行的應用

這些應用不是常駐內存的,意味著可以被任務管理器殺掉,但是在某些場景下用戶不會去殺。這類應用包括:音樂、下載等。用戶退出UI界面後,音樂還在繼續播放,下載程序還在運行。這時候音樂應該釋放部分UI資源和Cache。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved