Android 圖片加載圖片_OOM異常解決

http://stormzhang.github.io/android/2013/11/20/android-display-bitmaps-efficiently/ android

Android加載資源圖片時,很容易出現OOM的錯誤。
git

由於Android系統對內存有一個限制,若是超出該限制,就會出現OOM。爲了不這個問題,須要在加載資源時儘可能考慮如何節約內存,儘快釋放資源等等。github


Android系統版本對圖片加載,回收的影響:數組

1,在Android 2.3以及以後,採用的是併發回收機制,避免在回收內存時的卡頓現象。緩存

2,在Android 2.3.3(API Level 10)以及以前,Bitmap的backing pixel 數據存儲在native memory, 與Bitmap自己是分開的,Bitmap自己存儲在dalvik heap 中。致使其pixel數據不能判斷是否還須要使用,不能及時釋放,容易引發OOM錯誤。 從Android 3.0(API 11)開始,pixel數據與Bitmap一塊兒存儲在Dalvik heap中。併發


在加載圖片資源時,可採用如下一些方法來避免OOM的問題:spa

1,在Android 2.3.3以及以前,建議使用Bitmap.recycle()方法,及時釋放資源。code

2,在Android 3.0開始,可設置BitmapFactory.options.inBitmap值,(從緩存中獲取)達到重用Bitmap的目的。若是設置,則inPreferredConfig屬性值會被重用的Bitmap該屬性值覆蓋。orm

3,經過設置Options.inPreferredConfig值來下降內存消耗:圖片

     默認爲ARGB_8888: 每一個像素4字節. 共32位。

     Alpha_8: 只保存透明度,共8位,1字節。

     ARGB_4444: 共16位,2字節。

     RGB_565:共16位,2字節。

     若是不須要透明度,可把默認值ARGB_8888改成RGB_565,節約一半內存。

4,經過設置Options.inSampleSize 對大圖片進行壓縮,可先設置Options.inJustDecodeBounds,獲取Bitmap的外圍數據,寬和高等。而後計算壓縮比例,進行壓縮。

5,設置Options.inPurgeable和inInputShareable:讓系統能及時回收內存。

      inPurgeable:設置爲True,則使用BitmapFactory建立的Bitmap用於存儲Pixel的內存空間,在系統內存不足時能夠被回收,當應用須要再次訪問該Bitmap的Pixel時,系統會再次調用BitmapFactory 的decode方法從新生成Bitmap的Pixel數組。

                        設置爲False時,表示不能被回收。

      inInputShareable:設置是否深拷貝,與inPurgeable結合使用,inPurgeable爲false時,該參數無心義。 

                                  True:  share  a reference to the input data(inputStream, array,etc) 。 False :a deep copy。

6,使用decodeStream代替其餘decodeResource,setImageResource,setImageBitmap等方法來加載圖片。

     區別: 

      decodeStream直接讀取圖片字節碼,調用nativeDecodeAsset/nativeDecodeStream來完成decode。無需使用Java空間的一些額外處理過程,節省dalvik內存。可是因爲直接讀取字節碼,沒有處理過程,所以不會根據機器的各類分辨率來自動適應,須要在hdpi,mdpi和ldpi中分別配置相應的圖片資源,不然在不一樣分辨率機器上都是一樣的大小(像素點數量),顯示的實際大小不對。

      decodeResource會在讀取完圖片數據後,根據機器的分辨率,進行圖片的適配處理,致使增大了不少dalvik內存消耗。


       decodeStream調用過程:

             decodeStream(InputStream,Rect,Options) -> nativeDecodeAsset/nativeDecodeStream

       decodeResource調用過程:即finishDecode以後,調用額外的Java層的createBitmap方法,消耗更多dalvik內存。

             decodeResource(Resource,resId,Options)  -> decodeResourceStream (設置Options的inDensity和inTargetDensity參數)  -> decodeStream() (在完成Decode後,進行finishDecode操做)

             finishDecode() -> Bitmap.createScaleBitmap()(根據inDensity和inTargetDensity計算scale) -> Bitmap.createBitmap()


以上方法的組合使用,合理避免OOM錯誤。

相關文章
相關標籤/搜索