Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中的內存管理機制以及正確的使用方式

Android中的內存管理機制以及正確的使用方式

編輯:關於Android編程

概述

從操作系統的角度來說,內存就是一塊數據存儲區域,屬於可被操作系統調度的資源。現代多任務(進程)的操作系統中,內存管理尤為重要,操作系統需要為每一個進程合理的分配內存資源,所以可以從兩方面來理解操作系統的內存管理機制。

第一:分配機制。為每一個進程分配一個合理的內存大小,保證每一個進程能夠正常的運行,不至於內存不夠使用或者每個進程占用太多的內存。

第二:回收機制。在系統內存不足打的時候,需要有一個合理的回收再分配的機制,以保證新的進程可以正常運行。回收的時候就要殺死那些正在占有內存的進程,操作系統需要提供一個合理的殺死這些進程的機制,以保證更少的副作用。

而作為一個多進程的操作系統,Android系統對內存的管理,也是有一套自己的方法的。跟PC不一樣的是,Android作為一個移動操作系統,一般情況下,內存資源會比PC更少,所以就需要更加謹慎的管理內存。

Android中的內存管理機制

分配機制

Android為每個進程分配內存的時候,采用了彈性的分配方式,也就是剛開始並不會一下分配很多內存給每個進程,而是給每一個進程分配一個“夠用”的量。這個量是根據每一個設備實際的物理內存大小來決定的。隨著應用的運行,可能會發現當前的內存可能不夠使用了,這時候Android又會為每個進程分配一些額外的內存大小。但是這些額外的大小並不是隨意的,也是有限度的,系統不可能為每一個App分配無限大小的內除。

Android系統的宗旨是最大限度的讓更多的進程存活在內存中,因為這樣的話,下一次用戶再啟動應用,不需要重新創建進程,只需要恢復已有的進程就可以了,減少了應用的啟動時間,提高了用戶體驗。

回收機制

Android對內存的使用方式是“盡最大限度的使用”,這一點繼承了Linux的優點。Android會在內存中保存盡可能多的數據,即使有些進程不再使用了,但是它的數據還被存儲在內存中,所以Android現在不推薦顯式的“退出”應用。因為這樣,當用戶下次再啟動應用的時候,只需要恢復當前進程就可以了,不需要重新創建進程,這樣就可以減少應用的啟動時間。只有當Android系統發現內存不夠使用,需要回收內存的時候,Android系統就會需要殺死其他進程,來回收足夠的內存。但是Android也不是隨便殺死一個進程,比如說一個正在與用戶交互的進程,這種後果是可怕的。所以Android會有限清理那些已經不再使用的進程,以保證最小的副作用。

Android殺死進程有兩個參考條件:

進程優先級:

Android為每一個進程分配了優先級的概念,優先級越低的進程,被殺死的概率就更大。Android中總共有5個進程優先級。具體含義這裡不再給出。

前台進程:正常不會被殺死

可見進程:正常不會被殺死

服務進程:正常不會被殺死

後台進程:存放於一個LRU緩存列表中,先殺死處於列表尾部的進程

空進程:正常情況下,為了平衡系統整體性能,Android不保存這些進程

回收收益:

當Android系統開始殺死LRU緩存中的進程時,系統會判斷每個進程殺死後帶來的回收收益。因為Android總是傾向於殺死一個能回收更多內存的進程,從而可以殺死更少的進程,來獲取更多的內存。殺死的進程越少,對用戶體驗的影響就越小。

官方推薦的App內存使用方式是什麼樣的?

1、當Service完成任務後,盡量停止它。

因為有Service組件的進程,優先級最低也是服務進程,這會影響到系統的內存回收。IntentService可以很好地完成這個任務。

2、在UI不可見的時候,釋放掉一些只有UI使用的資源。

系統會根據onTrimMemory()回調方法的TRIM_MEMORY_UI_HIDDEN等級的事件,來通知App UI已經隱藏了。

3、在系統內存緊張的時候,盡可能多的釋放掉一些非重要資源。

系統會根據onTrimMemory()回調方法來通知內存緊張的狀態,App應該根據不同的內存緊張等級,來合理的釋放資源,以保證系統能夠回收更多內存。當系統回收到足夠多的內存時,就不用殺死進程了。

4、檢查自己最大可用的內存大小。

這對一些緩存框架很有用,因為正常情況下,緩存框架的緩存池大小應當指定為最大內存的百分比,這樣才能更好地適配更多的設備。通過getMemoryClass()和getLargeMemoryClass()來獲取可用內存大小的信息。

5、避免濫用Bitmap導致的內存浪費。

根據當前設備的分辨率來壓縮Bitmap是一個不錯的選擇,在使用完Bitmap後,記得要使用recycle()來釋放掉Bitmap。使用軟引用或者弱引用來引用一個Bitmap,使用LRU緩存來對Bitmap進行緩存。

6、使用針對內存優化過的數據容器。

針對移動設備內存有限的問題,Android提供了一套針對內存優化過的數據容器,來替代JDK原生提供的數據容器。但是缺點就是,時間復雜度被提高了。比如SparseArray、SparseBooleanArray、LongSparseArray、

7、意識到內存的過度消耗。

Enum類型占用的內存是常量的兩倍多,所以避免使用enum,直接使用常量。

每一個Java的類(包括匿名內部類)都需要500Byte的代碼。

每一個類的實例都有12-16 Byte的額外內存消耗。

注意類似於HashMap這種,內部還需要生成Class的數據容器,這會消耗更多內存。

8、抽象代碼也會帶來更多的內存消耗。

如果你的“抽象”設計實際上並沒有帶來多大好處,那麼就不要使用它。

9、使用nano protobufs 來序列化數據。

Google設計的一個語言和平台中立打的序列化協議,比XML更快、更小、更簡單。

10、避免使用依賴注入的框架。

依賴注入的框架需要開啟額外的服務,來掃描App中代碼的Annotation,所以需要額外的系統資源。

11、使用ZIP對齊的APK。

對APK做Zip對齊,會壓縮其內部的資源,運行時會占用更少的內存。

12、使用多進程。

一個符合Android內存管理機制的App應該是什麼樣的?

一個遵循Android內存管理機制的App。應該具有如下幾個特點:

1、更少的占用內存。

2、在合適的時候,合理的釋放系統資源。

3、在系統內存緊張的情況下,能釋放掉大部分不重要的資源,來為Android系統提供可用的內存。

4、能夠很合理的在特殊生命周期中,保存或者還原重要數據,以至於系統能夠正確的重新恢復該應用。

App為什麼要符合該內存管理機制?這樣做有什麼好處?

一個遵循Android的內存管理機制的App,在Android系統中,就是一個好的公民,那麼系統自然是傾向於保護這些良民,而去殺死那些素質不高的人。所以符合Android內存管理機制,對Android系統和App來說,是一個雙贏的過程。如果每一個App都遵循這種規則,那麼Android系統就會更加流暢,也會帶來更好的體驗,而App可以更長時間的駐留於內存中。

在這種管理方式下,如何編寫符合Android內存管理機制的App?

主要是參考官方推薦的內存使用方式,來設計和編寫App。

避免創建不必要的對象。

在合適的生命周期中,合理的管理資源。

在系統內存不足時,主動釋放更多的資源。

編寫Android應用時,如何更少的使用內存資源?

避免創建不需要的對象。

比如使用StringBuffer來代替很多個String相加的操作。

使用原始類型來代替包裝類型,int比Integer占用更少的資源。

兩個並行的屬性數組,優於一個包含這兩個屬性的對象的數組。這個在設計數據容器的時候會有意義,比如類A有兩個屬性A(int, String),使用 int[] 和 String[] 優於 A[]。

使用常量代替enum。

少用包裝類,能夠使用原始類型的,就使用原始類型。

App如果真的需要很多內存怎麼辦?

多進程

把消耗內存過大的模塊,或者需要長期在後台運行的模塊,移入到單獨的進程中運行。Android會為每一個進程單獨分配內存,所以理論上App就可以使用到更多的內存。但是多進程是一把雙刃劍,錯誤的使用,會帶來其他很多的問題,這裡不再詳細談這個話題。

申請大內存

在標簽中,把largeHeap設置為true,Android系統會為該應用額外分配內存。但是不要濫用這個方法。如果一個App真的需要大內存,比如需要打開很多大圖片的應用,可以使用這種方式。千萬不要因為OOM而使用這種方法,這個時候更應該去檢查App的代碼是否不合理。

開發人員應該注意的App內存管理方式?

內存溢出

內存溢出,就是OOM,也就是內存不夠用了。有一個典型的例子就是加載了很多沒有經過壓縮的Bitmap到內存中,這些Bitmap很大,但是又真的在被使用,必須要在內存中,所以這個時候內存就不夠用了。這個時候,App再申請更多內存的時候就不行了,系統會拋出OOM。

解決這種問題:1、減少每個對象占用的內存,比如壓縮圖片。2、申請大內存。

內存洩露

內存洩露,就是Memory Leak,也就是本來該被GC回收後還給系統的內存,並沒有被GC。多數是因為不合理的對象引用,當一個對象不再使用的時候,由於代碼問題,沒有正確的釋放引用,就導致了內存洩露。

解決這種問題:1、通過各種內存分析工具,比如MAT,分析運行時的內存映像文件,找出造成內存洩露的代碼,然後修改掉。2、適當的使用WeakReference。

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