Android Note - 內存優化

內存優化是Android性能優化的重點內容,通常來講,談及性能優化,確定避不開內存優化。雖然如今手機內存都很大,但並不意味着咱們的App在使用內存時能「隨心所欲」。這篇就簡單地總結一下關於內存優化要注意的一些事項。java


進程級別的內存策略

咱們知道,Android 系統是一個基於 Linux 的開源系統,使用的是 Dalvik / Android Runtime 做爲對應的虛擬機來執行代碼。底層內存分配機制在這裏就不詳述了,只看 Application Framework 這一層。緩存

首先,Android 中的內存分配由 ActivityManagerService 統一管理。這是一個很重要的類,除了內存管理以外,它還管理了 Activity 生命週期,啓動行爲,消息派發等功能。當用戶點擊應用的啓動圖標時, ActivityManagerService 會請求系統建立一個進程,當進程建立完成以後,綁定給 ActivityManagerService,這時纔會開始 App 自己的生命週期。性能優化

而關於內存回收這塊,Application Framework 給建立的進程規定了五個的回收類型優先級,即從最早被回收到最後被回收,分別是:網絡

  • Empty process 空進程
  • Background process 後臺進程
  • Service process 服務進程
  • Visible process 可見進程
  • Foreground process 前臺進程

而後在 ActivityManagerService 中,會對全部進程進行評分,並將評分同步到 Linux 內核中,最終由內核來執行內存回收框架


對象級別的內存策略

關於對象級別的內存管理策略,因爲是應用程序自動管理內存分配以及內存回收(Java GC),能操做的有限,可是基本的概念仍是要了解的,由於當你知道對象/變量在內存中是如何分配,以及分配到堆/棧/方法區的時候,在寫代碼的時候就會有意規避一些問題,達到內存優化的效果。異步


Android常見內存問題

內存泄漏

內存泄漏 Memory Leak,指的是內存申請並使用完畢之後,系統由於某些緣由沒法回收該內存塊的狀況。其實質也是長生命週期對象持有短生命週期的對象,致使短生命週期對象須要被回收時,因爲長生命週期的對象持有沒法被回收的現象。ide

在Android中,如下幾個場景容易出現內存泄漏。函數

單例對象使用了非全局的 Context佈局

這個是初學者容易犯的錯誤,在構造一個單例對象時,每每須要使用 Context 對象來初始化構造函數,並持有一個 Context對象,這時若是傳入一個非全局的 Context ,會致使該 Context對象在 GC 時沒法回收,形成內存泄漏。性能

解決方案:單例使用 ApplicationContext ,這個對象的生命週期是整個應用的生命週期,不會致使泄漏

匿名內部類 / 非靜態內部類 / 異步線程 / Handler 持有外部類的引用

這也是常見的內存泄漏易於出現的場景。舉例來講,咱們如今常用 Rxjava + Retrofit + OkHttp 來構建網絡請求。有時候會碰到網速過慢致使網絡請求返回慢或者超時的狀況。這時若是咱們關閉了當前頁面,網絡請求結果仍然會被觀察者接受並刷新UI。這時原本要被回收的UI對象因爲被觀察者持有,沒法回收,就致使了內存泄漏。

解決方案:

  1. 使用靜態內部類,並在須要的時候引入外部類,而不是直接在構造函數中引用
  2. 使用弱引用 WeakReference 來引用外部類實例(掌握Java的四種引用方式)

資源未關閉致使沒法回收

這也是常常被提到的點,註冊並使用後,忘記在生命週期結束時解綁,致使沒法回收。

解決方案:BroadcastReceiver、ContentObserver、File、Bitmap、Timer、EventBus 等都是須要解綁或者清空的,要養成直覺

WebView不要在佈局中定義

這個是網絡上一篇文章裏看到的,我想如今應該沒有多少人會在佈局裏定義 WebView 吧(還有 Fragment )

解決方案:在代碼中構造WebView對象,建立時上下文使用 ApplicationContext


內存溢出

內存溢出 Out Of Memory ,是指應用的內存申請超出了當前所能申請的最大內存容量,致使應用出現一系列問題甚至被系統殺掉進程。在 Android 中出現內存溢出,主要是由於如下緣由引發。

使用 Bitmap 而且未優化

Bitmap 是產生內存溢出的大戶,若是沒有通過任何優化,直接加載一個 Bitmap 的話,會致使該對象吃掉大量內存。

解決方案:

  1. 加載圖片以前先計算出合適的縮放比例,按比例縮放。
  2. 選擇合適的解碼格式。不一樣的格式,內存佔用在很大差別。
  3. Bitmap 不用時要及時回收,調用 recycle 方法。

短期建立大量對象

這個常見於列表組件的加載。加載列表時若是不優化,同一時間內建立了過多對象,就會形成內存溢出。

解決方案:

  1. 使用按需加載的方式加載內容(上拉加載更多)
  2. 經常使用對象作到儘可能複用,並緩存經常使用對象。

其餘內存溢出的場景和解決方案

  1. 捕獲 OOM 異常,避免由於內存溢出而致使崩潰
  2. 使用優化的數據容器,合適的內存容器能夠大幅度增長內存性能
  3. 使用 zipalign 對齊能夠必定量優化內存性能(Google 官方推薦)
  4. 使用成熟的第三方框架,例如使用 Glide 處理圖片
相關文章
相關標籤/搜索