編輯:關於Android編程
從操作系統的角度來說,內存就是一塊數據存儲區域,屬於可被操作系統調度的資源。現代多任務(進程)的操作系統中,內存管理尤為重要,操作系統需要為每一個進程合理的分配內存資源,所以可以從兩方面來理解操作系統的內存管理機制。
第一:分配機制。為每一個進程分配一個合理的內存大小,保證每一個進程能夠正常的運行,不至於內存不夠使用或者每個進程占用太多的內存。
第二:回收機制。在系統內存不足打的時候,需要有一個合理的回收再分配的機制,以保證新的進程可以正常運行。回收的時候就要殺死那些正在占有內存的進程,操作系統需要提供一個合理的殺死這些進程的機制,以保證更少的副作用。
而作為一個多進程的操作系統,Android系統對內存的管理,也是有一套自己的方法的。跟PC不一樣的是,Android作為一個移動操作系統,一般情況下,內存資源會比PC更少,所以就需要更加謹慎的管理內存。
Android為每個進程分配內存的時候,采用了彈性的分配方式,也就是剛開始並不會一下分配很多內存給每個進程,而是給每一個進程分配一個“夠用”的量。這個量是根據每一個設備實際的物理內存大小來決定的。隨著應用的運行,可能會發現當前的內存可能不夠使用了,這時候Android又會為每個進程分配一些額外的內存大小。但是這些額外的大小並不是隨意的,也是有限度的,系統不可能為每一個App分配無限大小的內除。
Android系統的宗旨是最大限度的讓更多的進程存活在內存中,因為這樣的話,下一次用戶再啟動應用,不需要重新創建進程,只需要恢復已有的進程就可以了,減少了應用的啟動時間,提高了用戶體驗。
Android對內存的使用方式是“盡最大限度的使用”,這一點繼承了Linux的優點。Android會在內存中保存盡可能多的數據,即使有些進程不再使用了,但是它的數據還被存儲在內存中,所以Android現在不推薦顯式的“退出”應用。因為這樣,當用戶下次再啟動應用的時候,只需要恢復當前進程就可以了,不需要重新創建進程,這樣就可以減少應用的啟動時間。只有當Android系統發現內存不夠使用,需要回收內存的時候,Android系統就會需要殺死其他進程,來回收足夠的內存。但是Android也不是隨便殺死一個進程,比如說一個正在與用戶交互的進程,這種後果是可怕的。所以Android會有限清理那些已經不再使用的進程,以保證最小的副作用。
Android殺死進程有兩個參考條件:
進程優先級:
Android為每一個進程分配了優先級的概念,優先級越低的進程,被殺死的概率就更大。Android中總共有5個進程優先級。具體含義這裡不再給出。
前台進程:正常不會被殺死
可見進程:正常不會被殺死
服務進程:正常不會被殺死
後台進程:存放於一個LRU緩存列表中,先殺死處於列表尾部的進程
空進程:正常情況下,為了平衡系統整體性能,Android不保存這些進程
回收收益:
當Android系統開始殺死LRU緩存中的進程時,系統會判斷每個進程殺死後帶來的回收收益。因為Android總是傾向於殺死一個能回收更多內存的進程,從而可以殺死更少的進程,來獲取更多的內存。殺死的進程越少,對用戶體驗的影響就越小。
因為有Service組件的進程,優先級最低也是服務進程,這會影響到系統的內存回收。IntentService可以很好地完成這個任務。
系統會根據onTrimMemory()回調方法的TRIM_MEMORY_UI_HIDDEN等級的事件,來通知App UI已經隱藏了。
系統會根據onTrimMemory()回調方法來通知內存緊張的狀態,App應該根據不同的內存緊張等級,來合理的釋放資源,以保證系統能夠回收更多內存。當系統回收到足夠多的內存時,就不用殺死進程了。
這對一些緩存框架很有用,因為正常情況下,緩存框架的緩存池大小應當指定為最大內存的百分比,這樣才能更好地適配更多的設備。通過getMemoryClass()和getLargeMemoryClass()來獲取可用內存大小的信息。
根據當前設備的分辨率來壓縮Bitmap是一個不錯的選擇,在使用完Bitmap後,記得要使用recycle()來釋放掉Bitmap。使用軟引用或者弱引用來引用一個Bitmap,使用LRU緩存來對Bitmap進行緩存。
針對移動設備內存有限的問題,Android提供了一套針對內存優化過的數據容器,來替代JDK原生提供的數據容器。但是缺點就是,時間復雜度被提高了。比如SparseArray、SparseBooleanArray、LongSparseArray、
Enum類型占用的內存是常量的兩倍多,所以避免使用enum,直接使用常量。
每一個Java的類(包括匿名內部類)都需要500Byte的代碼。
每一個類的實例都有12-16 Byte的額外內存消耗。
注意類似於HashMap這種,內部還需要生成Class的數據容器,這會消耗更多內存。
如果你的“抽象”設計實際上並沒有帶來多大好處,那麼就不要使用它。
Google設計的一個語言和平台中立打的序列化協議,比XML更快、更小、更簡單。
依賴注入的框架需要開啟額外的服務,來掃描App中代碼的Annotation,所以需要額外的系統資源。
對APK做Zip對齊,會壓縮其內部的資源,運行時會占用更少的內存。
一個遵循Android內存管理機制的App。應該具有如下幾個特點:
1、更少的占用內存。
2、在合適的時候,合理的釋放系統資源。
3、在系統內存緊張的情況下,能釋放掉大部分不重要的資源,來為Android系統提供可用的內存。
4、能夠很合理的在特殊生命周期中,保存或者還原重要數據,以至於系統能夠正確的重新恢復該應用。
一個遵循Android的內存管理機制的App,在Android系統中,就是一個好的公民,那麼系統自然是傾向於保護這些良民,而去殺死那些素質不高的人。所以符合Android內存管理機制,對Android系統和App來說,是一個雙贏的過程。如果每一個App都遵循這種規則,那麼Android系統就會更加流暢,也會帶來更好的體驗,而App可以更長時間的駐留於內存中。
主要是參考官方推薦的內存使用方式,來設計和編寫App。
避免創建不必要的對象。
在合適的生命周期中,合理的管理資源。
在系統內存不足時,主動釋放更多的資源。
避免創建不需要的對象。
比如使用StringBuffer來代替很多個String相加的操作。
使用原始類型來代替包裝類型,int比Integer占用更少的資源。
兩個並行的屬性數組,優於一個包含這兩個屬性的對象的數組。這個在設計數據容器的時候會有意義,比如類A有兩個屬性A(int, String),使用 int[] 和 String[] 優於 A[]。
使用常量代替enum。
少用包裝類,能夠使用原始類型的,就使用原始類型。
把消耗內存過大的模塊,或者需要長期在後台運行的模塊,移入到單獨的進程中運行。Android會為每一個進程單獨分配內存,所以理論上App就可以使用到更多的內存。但是多進程是一把雙刃劍,錯誤的使用,會帶來其他很多的問題,這裡不再詳細談這個話題。
在標簽中,把largeHeap設置為true,Android系統會為該應用額外分配內存。但是不要濫用這個方法。如果一個App真的需要大內存,比如需要打開很多大圖片的應用,可以使用這種方式。千萬不要因為OOM而使用這種方法,這個時候更應該去檢查App的代碼是否不合理。
內存溢出,就是OOM,也就是內存不夠用了。有一個典型的例子就是加載了很多沒有經過壓縮的Bitmap到內存中,這些Bitmap很大,但是又真的在被使用,必須要在內存中,所以這個時候內存就不夠用了。這個時候,App再申請更多內存的時候就不行了,系統會拋出OOM。
解決這種問題:1、減少每個對象占用的內存,比如壓縮圖片。2、申請大內存。
內存洩露,就是Memory Leak,也就是本來該被GC回收後還給系統的內存,並沒有被GC。多數是因為不合理的對象引用,當一個對象不再使用的時候,由於代碼問題,沒有正確的釋放引用,就導致了內存洩露。
解決這種問題:1、通過各種內存分析工具,比如MAT,分析運行時的內存映像文件,找出造成內存洩露的代碼,然後修改掉。2、適當的使用WeakReference。
根據人眼視覺殘留現象,連續播放一些列的圖像,形成動畫效果。Android中的動畫:游戲:利用自定義View的繪制方法,開啟線程頻繁的刷新界面,形成動畫; Android
首先給大家展示下效果圖:public class HomeEduMoreAdapter extends BaseAdapter {private final String
相信很多朋友都有過錯手把內存卡的數據刪掉,這是重要的文件該怎麼辦呢?還能恢復內存卡的數據嗎?小編告訴你,有辦法!錯誤刪除數據:1、如果朋友們真的錯手把重要的
記錄一下微信第三方實現登錄的方法。還是比較簡單。一、必要的准備工作1.首先需要注冊並被審核通過的微信開放平台帳號,然後創建一個移動應用,也需要被審核;2.然後到資源中心下