Android 內存管理之優化建議

OOM(OutOfMemory)轉:http://hukai.me/android-performance-oom/

前面咱們提到過使用getMemoryClass()的方法能夠獲得Dalvik Heap的閾值。簡要的獲取某個應用的內存佔用狀況能夠參考下面的示例( 關於更多內存查看的知識,能夠參考這篇官方教程:Investigating Your RAM Usage )html

1)查看內存使用狀況

  • 經過命令行查看內存詳細佔用狀況:

android_perf_oom_dumpsys_meminfo.png

  • 經過Android Studio的Memory Monitor查看內存中Dalvik Heap的實時變化

android_perf_oom_studio_mem_monitormemory_monitor_free_allocation memory_monitor_gc_event

2)發生OOM的條件

關於Native Heap,Dalvik Heap,Pss等內存管理機制比較複雜,這裏不展開描述。簡單的說,經過不一樣的內存分配方式(malloc/mmap/JNIEnv/etc)對不一樣的對象(bitmap,etc)進行操做會由於Android系統版本的差別而產生不一樣的行爲,對Native Heap與Dalvik Heap以及OOM的判斷條件都會有所影響。在2.x的系統上,咱們經常能夠看到Heap Size的total值明顯超過了經過getMemoryClass()獲取到的閾值而不會發生OOM的狀況,那麼針對2.x與4.x的Android系統,究竟是如何判斷會發生OOM呢?java

  • Android 2.x系統 GC LOG中的dalvik allocated + external allocated + 新分配的大小 >= getMemoryClass()值的時候就會發生OOM。 例如,假設有這麼一段Dalvik輸出的GC LOG:GC_FOR_MALLOC free 2K, 13% free 32586K/37455K, external 8989K/10356K, paused 20ms,那麼32586+8989+(新分配23975)=65550>64M時,就會發生OOM。android

  • Android 4.x系統 Android 4.x的系統廢除了external的計數器,相似bitmap的分配改到dalvik的java heap中申請,只要allocated + 新分配的內存 >= getMemoryClass()的時候就會發生OOM,以下圖所示(雖然圖示演示的是art運行環境,可是統計規則仍是和dalvik保持一致)git

android_perf_oom_gc_log.png

(三)如何避免OOM總結

前面介紹了一些基礎的內存管理機制以及OOM的基礎知識,那麼在實踐操做當中,有哪些指導性的規則能夠參考呢?概括下來,能夠從四個方面着手,首先是減少對象的內存佔用,其次是內存對象的重複利用,而後是避免對象的內存泄露,最後是內存使用策略優化。github

減少對象的內存佔用

避免OOM的第一步就是要儘可能減小新分配出來的對象佔用內存的大小,儘可能使用更加輕量的對象。算法

1)使用更加輕量的數據結構

例如,咱們能夠考慮使用ArrayMap/SparseArray而不是HashMap等傳統數據結構,下圖演示了HashMap的簡要工做原理,相比起Android系統專門爲移動操做系統編寫的ArrayMap容器,在大多數狀況下,都顯示效率低下,更佔內存。一般的HashMap的實現方式更加消耗內存,由於它須要一個額外的實例對象來記錄Mapping操做。另外,SparseArray更加高效在於他們避免了對key與value的autobox自動裝箱,而且避免了裝箱後的解箱。數據庫

android_perf_3_arraymap_key_value

關於更多ArrayMap/SparseArray的討論,請參考http://hukai.me/android-performance-patterns-season-3/的前三個段落編程

2)避免在Android裏面使用Enum

Android官方培訓課程提到過「Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.」,具體原理請參考http://hukai.me/android-performance-patterns-season-3/,因此請避免在Android裏面使用到枚舉。緩存

3)減少Bitmap對象的內存佔用

Bitmap是一個極容易消耗內存的大胖子,減少建立出來的Bitmap的內存佔用是很重要的,一般來講有下面2個措施:性能優化

  • inSampleSize:縮放比例,在把圖片載入內存以前,咱們須要先計算出一個合適的縮放比例,避免沒必要要的大圖載入。
  • decode format:解碼格式,選擇ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差別。

4)使用更小的圖片

在設計給到資源圖片的時候,咱們須要特別留意這張圖片是否存在能夠壓縮的空間,是否可使用一張更小的圖片。儘可能使用更小的圖片不只僅能夠減小內存的使用,還能夠避免出現大量的InflationException。假設有一張很大的圖片被XML文件直接引用,頗有可能在初始化視圖的時候就會由於內存不足而發生InflationException,這個問題的根本緣由實際上是發生了OOM。

內存對象的重複利用

大多數對象的複用,最終實施的方案都是利用對象池技術,要麼是在編寫代碼的時候顯式的在程序裏面去建立對象池,而後處理好複用的實現邏輯,要麼就是利用系統框架既有的某些複用特性達到減小對象的重複建立,從而減小內存的分配與回收。

android_perf_2_object_pool

在Android上面最經常使用的一個緩存算法是LRU(Least Recently Use),簡要操做原理以下圖所示:

android_perf_2_lru_mode

1)複用系統自帶的資源

Android系統自己內置了不少的資源,例如字符串/顏色/圖片/動畫/樣式以及簡單佈局等等,這些資源均可以在應用程序中直接引用。這樣作不只僅能夠減小應用程序的自身負重,減少APK的大小,另外還能夠必定程度上減小內存的開銷,複用性更好。可是也有必要留意Android系統的版本差別性,對那些不一樣系統版本上表現存在很大差別,不符合需求的狀況,仍是須要應用程序自身內置進去。

2)注意在ListView/GridView等出現大量重複子組件的視圖裏面對ConvertView的複用

android_perf_oom_listview_recycle

3)Bitmap對象的複用

  • 在ListView與GridView等顯示大量圖片的控件裏面須要使用LRU的機制來緩存處理好的Bitmap。

android_perf_2_inbitmap_old

  • 利用inBitmap的高級特性提升Android系統在Bitmap分配與釋放執行效率上的提高(3.0以及4.4之後存在一些使用限制上的差別)。使用inBitmap屬性能夠告知Bitmap解碼器去嘗試使用已經存在的內存區域,新解碼的bitmap會嘗試去使用以前那張bitmap在heap中所佔據的pixel data內存區域,而不是去問內存從新申請一塊區域來存放bitmap。利用這種特性,即便是上千張的圖片,也只會僅僅只須要佔用屏幕所可以顯示的圖片數量的內存大小。

android_perf_2_inbitmap_new

使用inBitmap須要注意幾個限制條件:

  • 在SDK 11 -> 18之間,重用的bitmap大小必須是一致的,例如給inBitmap賦值的圖片大小爲100-100,那麼新申請的bitmap必須也爲100-100纔可以被重用。從SDK 19開始,新申請的bitmap大小必須小於或者等於已經賦值過的bitmap大小。
  • 新申請的bitmap與舊的bitmap必須有相同的解碼格式,例如你們都是8888的,若是前面的bitmap是8888,那麼就不能支持4444與565格式的bitmap了。 咱們能夠建立一個包含多種典型可重用bitmap的對象池,這樣後續的bitmap建立都可以找到合適的「模板」去進行重用。以下圖所示:

android_perf_2_inbitmap_pool

另外提一點:在2.x的系統上,儘管bitmap是分配在native層,可是仍是沒法避免被計算到OOM的引用計數器裏面。這裏提示一下,很多應用會經過反射BitmapFactory.Options裏面的inNativeAlloc來達到擴大使用內存的目的,可是若是你們都這麼作,對系統總體會形成必定的負面影響,建議謹慎採納。

4)避免在onDraw方法裏面執行對象的建立

相似onDraw等頻繁調用的方法,必定須要注意避免在這裏作建立對象的操做,由於他會迅速增長內存的使用,並且很容易引發頻繁的gc,甚至是內存抖動。

5)StringBuilder

在有些時候,代碼中會須要使用到大量的字符串拼接的操做,這種時候有必要考慮使用StringBuilder來替代頻繁的「+」。

避免對象的內存泄露

內存對象的泄漏,會致使一些再也不使用的對象沒法及時釋放,這樣一方面佔用了寶貴的內存空間,很容易致使後續須要分配內存的時候,空閒空間不足而出現OOM。顯然,這還使得每級Generation的內存區域可用空間變小,gc就會更容易被觸發,容易出現內存抖動,從而引發性能問題。

android_perf_3_leak

最新的LeakCanary開源控件,能夠很好的幫助咱們發現內存泄露的狀況,更多關於LeakCanary的介紹,請看這裏https://github.com/square/leakcanary(中文使用說明http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/)。另外也可使用傳統的MAT工具查找內存泄露,請參考這裏http://android-developers.blogspot.pt/2011/03/memory-analysis-for-android.html(便捷的中文資料http://androidperformance.com/2015/04/11/AndroidMemory-Usage-Of-MAT/

1)注意Activity的泄漏

一般來講,Activity的泄漏是內存泄漏裏面最嚴重的問題,它佔用的內存多,影響面廣,咱們須要特別注意如下兩種狀況致使的Activity泄漏:

  • 內部類引用致使Activity的泄漏

最典型的場景是Handler致使的Activity泄漏,若是Handler中有延遲的任務或者是等待執行的任務隊列過長,都有可能由於Handler繼續執行而致使Activity發生泄漏。此時的引用關係鏈是Looper -> MessageQueue -> Message -> Handler -> Activity。爲了解決這個問題,能夠在UI退出以前,執行remove Handler消息隊列中的消息與runnable對象。或者是使用Static + WeakReference的方式來達到斷開Handler與Activity之間存在引用關係的目的。

  • Activity Context被傳遞到其餘實例中,這可能致使自身被引用而發生泄漏。

內部類引發的泄漏不只僅會發生在Activity上,其餘任何內部類出現的地方,都須要特別留意!咱們能夠考慮儘可能使用static類型的內部類,同時使用WeakReference的機制來避免由於互相引用而出現的泄露。

2)考慮使用Application Context而不是Activity Context

對於大部分非必須使用Activity Context的狀況(Dialog的Context就必須是Activity Context),咱們均可以考慮使用Application Context而不是Activity的Context,這樣能夠避免不經意的Activity泄露。

3)注意臨時Bitmap對象的及時回收

雖然在大多數狀況下,咱們會對Bitmap增長緩存機制,可是在某些時候,部分Bitmap是須要及時回收的。例如臨時建立的某個相對比較大的bitmap對象,在通過變換獲得新的bitmap對象以後,應該儘快回收原始的bitmap,這樣可以更快釋放原始bitmap所佔用的空間。

須要特別留意的是Bitmap類裏面提供的createBitmap()方法:

android_perf_oom_create_bitmap.png

這個函數返回的bitmap有可能和source bitmap是同一個,在回收的時候,須要特別檢查source bitmap與return bitmap的引用是否相同,只有在不等的狀況下,纔可以執行source bitmap的recycle方法。

4)注意監聽器的註銷

在Android程序裏面存在不少須要register與unregister的監聽器,咱們須要確保在合適的時候及時unregister那些監聽器。本身手動add的listener,須要記得及時remove這個listener。

5)注意緩存容器中的對象泄漏

有時候,咱們爲了提升對象的複用性把某些對象放到緩存容器中,但是若是這些對象沒有及時從容器中清除,也是有可能致使內存泄漏的。例如,針對2.3的系統,若是把drawable添加到緩存容器,由於drawable與View的強應用,很容易致使activity發生泄漏。而從4.0開始,就不存在這個問題。解決這個問題,須要對2.3系統上的緩存drawable作特殊封裝,處理引用解綁的問題,避免泄漏的狀況。

6)注意WebView的泄漏

Android中的WebView存在很大的兼容性問題,不只僅是Android系統版本的不一樣對WebView產生很大的差別,另外不一樣的廠商出貨的ROM裏面WebView也存在着很大的差別。更嚴重的是標準的WebView存在內存泄露的問題,看這裏WebView causes memory leak - leaks the parent Activity。因此一般根治這個問題的辦法是爲WebView開啓另一個進程,經過AIDL與主進程進行通訊,WebView所在的進程能夠根據業務的須要選擇合適的時機進行銷燬,從而達到內存的完整釋放。

7)注意Cursor對象是否及時關閉

在程序中咱們常常會進行查詢數據庫的操做,但時常會存在不當心使用Cursor以後沒有及時關閉的狀況。這些Cursor的泄露,反覆屢次出現的話會對內存管理產生很大的負面影響,咱們須要謹記對Cursor對象的及時關閉。

內存使用策略優化

1)謹慎使用large heap

正如前面提到的,Android設備根據硬件與軟件的設置差別而存在不一樣大小的內存空間,他們爲應用程序設置了不一樣大小的Heap限制閾值。你能夠經過調用getMemoryClass()來獲取應用的可用Heap大小。在一些特殊的情景下,你能夠經過在manifestapplication標籤下添加largeHeap=true的屬性來爲應用聲明一個更大的heap空間。而後,你能夠經過getLargeMemoryClass()來獲取到這個更大的heap size閾值。然而,聲明獲得更大Heap閾值的本意是爲了一小部分會消耗大量RAM的應用(例如一個大圖片的編輯應用)。不要輕易的由於你須要使用更多的內存而去請求一個大的Heap Size。只有當你清楚的知道哪裏會使用大量的內存而且知道爲何這些內存必須被保留時纔去使用large heap。所以請謹慎使用large heap屬性。使用額外的內存空間會影響系統總體的用戶體驗,而且會使得每次gc的運行時間更長。在任務切換時,系統的性能會大打折扣。另外, large heap並不必定可以獲取到更大的heap。在某些有嚴格限制的機器上,large heap的大小和一般的heap size是同樣的。所以即便你申請了large heap,你仍是應該經過執行getMemoryClass()來檢查實際獲取到的heap大小。

2)綜合考慮設備內存閾值與其餘因素設計合適的緩存大小

例如,在設計ListView或者GridView的Bitmap LRU緩存的時候,須要考慮的點有:

  • 應用程序剩下了多少可用的內存空間?
  • 有多少圖片會被一次呈現到屏幕上?有多少圖片須要事先緩存好以便快速滑動時可以當即顯示到屏幕?
  • 設備的屏幕大小與密度是多少? 一個xhdpi的設備會比hdpi須要一個更大的Cache來hold住一樣數量的圖片。
  • 不一樣的頁面針對Bitmap的設計的尺寸與配置是什麼,大概會花費多少內存?
  • 頁面圖片被訪問的頻率?是否存在其中的一部分比其餘的圖片具備更高的訪問頻繁?若是是,也許你想要保存那些最常訪問的到內存中,或者爲不一樣組別的位圖(按訪問頻率分組)設置多個LruCache容器。

3)onLowMemory()與onTrimMemory()

Android用戶能夠隨意在不一樣的應用之間進行快速切換。爲了讓background的應用可以迅速的切換到forground,每個background的應用都會佔用必定的內存。Android系統會根據當前的系統的內存使用狀況,決定回收部分background的應用內存。若是background的應用從暫停狀態直接被恢復到forground,可以得到較快的恢復體驗,若是background應用是從Kill的狀態進行恢復,相比之下就顯得稍微有點慢。

android_perf_3_memory_bg_2_for

  • onLowMemory():Android系統提供了一些回調來通知當前應用的內存使用狀況,一般來講,當全部的background應用都被kill掉的時候,forground應用會收到onLowMemory()的回調。在這種狀況下,須要儘快釋放當前應用的非必須的內存資源,從而確保系統可以繼續穩定運行。
  • onTrimMemory(int):Android系統從4.0開始還提供了onTrimMemory()的回調,當系統內存達到某些條件的時候,全部正在運行的應用都會收到這個回調,同時在這個回調裏面會傳遞如下的參數,表明不一樣的內存使用狀況,收到onTrimMemory()回調的時候,須要根據傳遞的參數類型進行判斷,合理的選擇釋放自身的一些內存佔用,一方面能夠提升系統的總體運行流暢度,另外也能夠避免本身被系統判斷爲優先須要殺掉的應用。下圖介紹了各類不一樣的回調參數:

  • TRIM_MEMORY_UI_HIDDEN:你的應用程序的全部UI界面被隱藏了,即用戶點擊了Home鍵或者Back鍵退出應用,致使應用的UI界面徹底不可見。這個時候應該釋放一些不可見的時候非必須的資源

當程序正在前臺運行的時候,可能會接收到從onTrimMemory()中返回的下面的值之一:

  • TRIM_MEMORY_RUNNING_MODERATE:你的應用正在運行而且不會被列爲可殺死的。可是設備此時正運行於低內存狀態下,系統開始觸發殺死LRU Cache中的Process的機制。
  • TRIM_MEMORY_RUNNING_LOW:你的應用正在運行且沒有被列爲可殺死的。可是設備正運行於更低內存的狀態下,你應該釋放不用的資源用來提高系統性能。
  • TRIM_MEMORY_RUNNING_CRITICAL:你的應用仍在運行,可是系統已經把LRU Cache中的大多數進程都已經殺死,所以你應該當即釋放全部非必須的資源。若是系統不能回收到足夠的RAM數量,系統將會清除全部的LRU緩存中的進程,而且開始殺死那些以前被認爲不該該殺死的進程,例如那個包含了一個運行態Service的進程。

當應用進程退到後臺正在被Cached的時候,可能會接收到從onTrimMemory()中返回的下面的值之一:

  • TRIM_MEMORY_BACKGROUND: 系統正運行於低內存狀態而且你的進程正處於LRU緩存名單中最不容易殺掉的位置。儘管你的應用進程並非處於被殺掉的高危險狀態,系統可能已經開始殺掉LRU緩存中的其餘進程了。你應該釋放那些容易恢復的資源,以便於你的進程能夠保留下來,這樣當用戶回退到你的應用的時候纔可以迅速恢復。
  • TRIM_MEMORY_MODERATE: 系統正運行於低內存狀態而且你的進程已經已經接近LRU名單的中部位置。若是系統開始變得更加內存緊張,你的進程是有可能被殺死的。
  • TRIM_MEMORY_COMPLETE: 系統正運行於低內存的狀態而且你的進程正處於LRU名單中最容易被殺掉的位置。你應該釋聽任何不影響你的應用恢復狀態的資源。

android_perf_3_memory_ontrimmemory

  • 由於onTrimMemory()的回調是在API 14才被加進來的,對於老的版本,你可使用onLowMemory)回調來進行兼容。onLowMemory至關與TRIM_MEMORY_COMPLETE。
  • 請注意:當系統開始清除LRU緩存中的進程時,雖然它首先按照LRU的順序來執行操做,可是它一樣會考慮進程的內存使用量以及其餘因素。佔用越少的進程越容易被留下來。

4)資源文件須要選擇合適的文件夾進行存放

咱們知道hdpi/xhdpi/xxhdpi等等不一樣dpi的文件夾下的圖片在不一樣的設備上會通過scale的處理。例如咱們只在hdpi的目錄下放置了一張100100的圖片,那麼根據換算關係,xxhdpi的手機去引用那張圖片就會被拉伸到200200。須要注意到在這種狀況下,內存佔用是會顯著提升的。對於不但願被拉伸的圖片,須要放到assets或者nodpi的目錄下。

5)Try catch某些大內存分配的操做

在某些狀況下,咱們須要事先評估那些可能發生OOM的代碼,對於這些可能發生OOM的代碼,加入catch機制,能夠考慮在catch裏面嘗試一次降級的內存分配操做。例如decode bitmap的時候,catch到OOM,能夠嘗試把採樣比例再增長一倍以後,再次嘗試decode。

6)謹慎使用static對象

由於static的生命週期過長,和應用的進程保持一致,使用不當極可能致使對象泄漏,在Android中應該謹慎使用static對象。

android_perf_3_leak_static

7)特別留意單例對象中不合理的持有

雖然單例模式簡單實用,提供了不少便利性,可是由於單例的生命週期和應用保持一致,使用不合理很容易出現持有對象的泄漏。

8)珍惜Services資源

若是你的應用須要在後臺使用service,除非它被觸發並執行一個任務,不然其餘時候Service都應該是中止狀態。另外須要注意當這個service完成任務以後由於中止service失敗而引發的內存泄漏。 當你啓動一個Service,系統會傾向爲了保留這個Service而一直保留Service所在的進程。這使得進程的運行代價很高,由於系統沒有辦法把Service所佔用的RAM空間騰出來讓給其餘組件,另外Service還不能被Paged out。這減小了系統可以存放到LRU緩存當中的進程數量,它會影響應用之間的切換效率,甚至會致使系統內存使用不穩定,從而沒法繼續保持住全部目前正在運行的service。 建議使用IntentService,它會在處理完交代給它的任務以後儘快結束本身。更多信息,請閱讀Running in a Background Service

9)優化佈局層次,減小內存消耗

越扁平化的視圖佈局,佔用的內存就越少,效率越高。咱們須要儘可能保證佈局足夠扁平化,當使用系統提供的View沒法實現足夠扁平的時候考慮使用自定義View來達到目的。

10)謹慎使用「抽象」編程

不少時候,開發者會使用抽象類做爲」好的編程實踐」,由於抽象可以提高代碼的靈活性與可維護性。然而,抽象會致使一個顯著的額外內存開銷:他們須要同等量的代碼用於可執行,那些代碼會被mapping到內存中,所以若是你的抽象沒有顯著的提高效率,應該儘可能避免他們。

11)使用nano protobufs序列化數據

Protocol buffers是由Google爲序列化結構數據而設計的,一種語言無關,平臺無關,具備良好的擴展性。相似XML,卻比XML更加輕量,快速,簡單。若是你須要爲你的數據實現序列化與協議化,建議使用nano protobufs。關於更多細節,請參考protobuf readme的」Nano version」章節。

12)謹慎使用依賴注入框架

使用相似Guice或者RoboGuice等框架注入代碼,在某種程度上能夠簡化你的代碼。下面是使用RoboGuice先後的對比圖:

android_perf_oom_roboguice_1 android_perf_oom_roboguice_2

使用RoboGuice以後,代碼是簡化了很多。然而,那些注入框架會經過掃描你的代碼執行許多初始化的操做,這會致使你的代碼須要大量的內存空間來mapping代碼,並且mapped pages會長時間的被保留在內存中。除非真的頗有必要,建議謹慎使用這種技術。

13)謹慎使用多進程

使用多進程能夠把應用中的部分組件運行在單獨的進程當中,這樣能夠擴大應用的內存佔用範圍,可是這個技術必須謹慎使用,絕大多數應用都不該該貿然使用多進程,一方面是由於使用多進程會使得代碼邏輯更加複雜,另外若是使用不當,它可能反而會致使顯著增長內存。當你的應用須要運行一個常駐後臺的任務,並且這個任務並不輕量,能夠考慮使用這個技術。

一個典型的例子是建立一個能夠長時間後臺播放的Music Player。若是整個應用都運行在一個進程中,當後臺播放的時候,前臺的那些UI資源也沒有辦法獲得釋放。相似這樣的應用能夠切分紅2個進程:一個用來操做UI,另一個給後臺的Service。

14)使用ProGuard來剔除不須要的代碼

ProGuard可以經過移除不須要的代碼,重命名類,域與方法等等對代碼進行壓縮,優化與混淆。使用ProGuard可使得你的代碼更加緊湊,這樣可以減小mapping代碼所須要的內存空間。

15)謹慎使用第三方libraries

不少開源的library代碼都不是爲移動網絡環境而編寫的,若是運用在移動設備上,並不必定適合。即便是針對Android而設計的library,也須要特別謹慎,特別是在你不知道引入的library具體作了什麼事情的時候。例如,其中一個library使用的是nano protobufs, 而另一個使用的是micro protobufs。這樣一來,在你的應用裏面就有2種protobuf的實現方式。這樣相似的衝突還可能發生在輸出日誌,加載圖片,緩存等等模塊裏面。另外不要爲了1個或者2個功能而導入整個library,若是沒有一個合適的庫與你的需求相吻合,你應該考慮本身去實現,而不是導入一個大而全的解決方案。

16)考慮不一樣的實現方式來優化內存佔用

在某些狀況下,設計的某個方案可以快速實現需求,可是這個方案卻可能在內存佔用上表現的效率不夠好。例如:

android_perf_2_waer_animation

對於上面這樣一個時鐘錶盤的實現,最簡單的就是使用不少張包含指針的錶盤圖片,使用幀動畫實現指針的旋轉。可是若是把指針扣出來,單獨進行旋轉繪製,顯然比載入N多張圖片佔用的內存要少不少。固然這樣作,代碼複雜度上會有所增長,這裏就須要在優化內存佔用與實現簡易度之間進行權衡了。


寫在最後:

  • 設計風格很大程度上會影響到程序的內存與性能,相對來講,若是大量使用相似Material Design的風格,不只安裝包能夠變小,還能夠減小內存的佔用,渲染性能與加載性能都會有必定的提高。
  • 內存優化並不就是說程序佔用的內存越少就越好,若是由於想要保持更低的內存佔用,而頻繁觸發執行gc操做,在某種程度上反而會致使應用性能總體有所降低,這裏須要綜合考慮作必定的權衡。
  • Android的內存優化涉及的知識面還有不少:內存管理的細節,垃圾回收的工做原理,如何查找內存泄漏等等均可以展開講不少。OOM是內存優化當中比較突出的一點,儘可能減小OOM的機率對內存優化有着很大的意義。

參考資料:

相關文章
相關標籤/搜索