Android開發內存優化建議

本文主要記錄日常開發中關于內存管理的使用建議,便于查找。大部分來自郭霖的博客,轉載地址http://blog.csdn.net/guolin_blog/article/details/42238627

謹慎使用Service

在使用Service來執行后臺任務時,盡量在需要時才啟動Service;且在任務完成后,主動調用stopService或unbindService停止任務。注意,需要Service停止失敗導致內存泄漏的問題。

當啟用Service時,安卓系統會傾向于盡量保留Service所在進程,耗費系統內存。##Android官方推薦使用IntentService,該組件在后臺任務執行結束后可以自動停止##,盡量避免了內存泄漏的可能。

使用優化過的數據集合

Android API當中提供了一些優化過后的數據集合工具類,如SparseArray,SparseBooleanArray,以及LongSparseArray等,使用這些API可以讓我們的程序更加高效。傳統Java API中提供的HashMap工具類會相對比較低效,因為它需要為每一個鍵值對都提供一個對象入口,而SparseArray就避免掉了基本數據類型轉換成對象數據類型的時間。

Bitmap使用

Bitmap對象占用的內存空間與像素有直接的關系,且與圖片在硬盤中的大小無關,建議不要加載不需要的分辨率。以一張100k的圖片為例,像素是15001000,使用ARGB_8888的顏色類型,則每個像素點會占用4個字節的內存,占用的總內存是15001000*4字節,即5.7M。

BitmapFactory這個類提供了多個解析方法(decodeByteArray, decodeFile, decodeResource等)用于創建Bitmap對象,我們應該根據圖片的來源選擇合適的方法。比如SD卡中的圖片可以使用decodeFile方法,網絡上的圖片可以使用decodeStream方法,資源文件中的圖片可以使用decodeResource方法。這些方法會嘗試為已經構建的bitmap分配內存,如果內存不足就會出現OOM。為此每一種解析方法都提供了一個可選的BitmapFactory.Options參數,將這個參數的inJustDecodeBounds屬性設置為true就可以讓解析方法禁止為bitmap分配內存,返回值也不再是一個Bitmap對象,而是null。雖然Bitmap是null了,但是BitmapFactory.Options的outWidth、outHeight和outMimeType屬性都會被賦值。這個技巧讓我們可以在加載圖片之前就獲取到圖片的長寬值和MIME類型,從而根據情況對圖片進行壓縮。

當加載多圖時,可以考慮使用內存緩存LruCache來快速訪問圖片。該類在android-support-v4包中提供,主要的原理是把最近使用的對象用強引用存儲在 LinkedHashMap 中,并且把最近最少使用的對象在緩存值達到預設定值之前從內存中移除。

目前不建議使用軟引用或弱引用 (SoftReference or WeakReference)來實現內存緩存,因為從 Android 2.3 (API Level 9)開始,垃圾回收器會更傾向于回收持有軟引用或弱引用的對象,這讓軟引用和弱引用變得不再可靠。另外,Android 3.0 (API Level 11)中,圖片的數據會存儲在本地的內存當中,因而無法用一種可預見的方式將其釋放,這就有潛在的風險造成應用程序的內存溢出并崩潰。

還有一種磁盤緩存DiskLruCache可用來實現圖片的磁盤緩存,解決內存緩存空間有限的問題。DiskLruCache是非Google官方編寫,但獲得官方認證的硬盤緩存類,后續需要學習該類的原理和使用方法。

內存的開支情況

我們還應當清楚我們所使用語言的內存開支和消耗情況,并且在整個軟件的設計和開發當中都應該將這些信息考慮在內。可能有一些看起來無關痛癢的寫法,結果卻會導致很大一部分的內存開支,例如:

  • 使用枚舉通常會比使用靜態常量要消耗兩倍以上的內存,在Android開發當中我們應當盡可能地不使用枚舉。
  • 任何一個Java類,包括內部類、匿名類,都要占用大概500字節的內存空間。
  • 任何一個類的實例要消耗12-16字節的內存開支,因此頻繁創建實例也是會一定程序上影響內存的。eg不要在onDraw中頻繁創建對象
  • 在使用HashMap時,即使你只設置了一個基本數據類型的鍵,比如說int,但是也會按照對象的大小來分配內存,大概是32字節,而不是4字節。因此最好的辦法就是像上面所說的一樣,使用優化過的數據集合。

避免使用依賴注入框架

這類框架一般使用注解實現,可以省略findViewById()這一類的繁瑣操作,簡化一些編碼。但是這些框架為了要搜尋代碼中的注解,通常都需要經歷較長的初始化過程,并且還可能將一些你用不到的對象也一并加載到內存當中。這些用不到的對象會一直占用著內存空間,可能要過很久之后才會得到釋放,相較之下,也許多敲幾行看似繁瑣的代碼才是更好的選擇。

使用ProGuard簡化代碼

ProGuard相信大家都不會陌生,很多人都會使用這個工具來混淆代碼,但是除了混淆之外,它還具有壓縮和優化代碼的功能。ProGuard會對我們的代碼進行檢索,刪除一些無用的代碼,并且會對類、字段、方法等進行重命名,重命名之后的類、字段和方法名都會比原來簡短很多,這樣的話也就對內存的占用變得更少了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • HereAndroid的內存優化是性能優化中很重要的一部分,而避免OOM又是內存優化中比較核心的一點。這是一篇關于...
    HarryXR閱讀 3,853評論 1 24
  • 本文轉載來源 http://www.csdn.net/article/2015-09-18/2825737/1 (...
    yoosir閱讀 1,138評論 0 5
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,455評論 25 708
  • 如何避免OOM 一、減小對象的內存占用 1、使用更加輕量的數據結構 例如,我們可以考慮使用ArrayMap/Spa...
    呂侯爺閱讀 746評論 0 5
  • 沒有蠟燭的蛋糕 沒有她的笑 空蕩蕩的房間 沒有一絲溫暖 獨自一人 吃著冷掉的披薩 舔著發酸的奶油 喝著走氣的啤酒...
    韓伊筱曉閱讀 279評論 0 0