Android中Bitmap的使用

Bitmap使用需要注意哪些問題 ?

  1. 要選擇合適的圖片規格(bitmap類型):通常我們優化Bitmap時,當需要做性能優化或者防止OOM,==我們通常會使用RGB_565==,因爲ALPHA_8只有透明度,顯示一般圖片沒有意義,Bitmap.Config.ARGB_4444顯示圖片不清楚,Bitmap.Config.ARGB_8888佔用內存最多。:
  • ALPHA_8 每個像素佔用1byte內存
  • ARGB_4444 每個像素佔用2byte內存
  • ARGB_8888 每個像素佔用4byte內存(默認)
  • RGB_565 每個像素佔用2byte內存
  1. 降低採樣率:BitmapFactory.Options 參數inSampleSize的使用,先把options.inJustDecodeBounds設爲true,只是去讀取圖片的大小,在拿到圖片的大小之後和要顯示的大小做比較通過calculateInSampleSize()函數計算inSampleSize的具體值,得到值之後。options.inJustDecodeBounds設爲false讀圖片資源。
  2. 複用內存:即通過軟引用(內存不夠的時候纔會回收掉),複用內存塊,不需要再重新給這個bitmap申請一塊新的內存,避免了一次內存的分配和回收,從而改善了運行效率。
  3. 使用recycle()方法及時回收內存。
  4. 壓縮圖片。

Bitmap.recycle()會立即回收麼?什麼時候會回收?如果沒有地方使用這個Bitmap,爲什麼垃圾回收不會直接回收?

  • 加載Bitmap到內存裏以後,是包含兩部分內存區域的。簡單的說,一部分是Java部分的,一部分是C部分的。這個Bitmap對象是由Java部分分配的,不用的時候系統就會自動回收了。
  • 但是那個對應的C可用的內存區域,虛擬機是不能直接回收的,這個只能調用底層的功能釋放。所以需要==調用recycle()方法來釋放C部分的內存==
  • bitmap.recycle()方法用於回收該Bitmap所佔用的內存,接着將bitmap置空,最後使用System.gc()調用一下系統的垃圾回收器進行回收,調用System.gc()並不能保證立即開始進行回收過程,而只是爲了加快回收的到來。

一張Bitmap所佔內存以及內存佔用的計算

  • Bitamp 所佔內存大小 = 寬度像素 x (inTargetDensity / inDensity) x 高度像素 x (inTargetDensity / inDensity)x 一個像素所佔的內存字節大小

注:這裏inDensity表示目標圖片的dpi(放在哪個資源文件夾下),inTargetDensity表示目標屏幕的dpi,所以你可以發現inDensity和inTargetDensity會對Bitmap的寬高進行拉伸,進而改變Bitmap佔用內存的大小。

  • 在Bitmap裏有兩個獲取內存佔用大小的方法。
  1. getByteCount():API12 加入,代表存儲 Bitmap 的像素需要的最少內存。
  2. getAllocationByteCount():API19 加入,代表在內存中爲 Bitmap 分配的內存大小,代替了 getByteCount() 方法。
  3. 在不復用 Bitmap 時,getByteCount() 和 getAllocationByteCount 返回的結果是一樣的。在通過複用 Bitmap 來解碼圖片時,那麼 getByteCount() 表示新解碼圖片佔用內存的大 小,getAllocationByteCount() 表示被複用 Bitmap 真實佔用的內存大小。

圖片的三級緩存中,圖片加載到內存中,如果內存快爆了,會發生什麼?怎麼處理?

首先我們要清楚圖片的三級緩存是如何的

image.png

如果內存足夠時不回收。內存不夠時就回收軟引用對象。

內存中如果加載一張500*500的png高清圖片.應該是佔用多少的內存?

不考慮屏幕比的話:佔用內存=500 * 500 * 4 = 1000000B ≈ 0.95MB
考慮屏幕比的的話:佔用內存= 寬度像素 x (inTargetDensity / inDensity) x 高度像素 x (inTargetDensity / inDensity)x 一個像素所佔的內存字節大小
inDensity表示目標圖片的dpi(放在哪個資源文件夾下),inTargetDensity表示目標屏幕的dpi

image.png

Bitmap如何處理大圖,如一張30M的大圖,如何預防OOM?

避免OOM的問題就需要對大圖片的加載進行管理,主要通過縮放來減小圖片的內存佔用。

  • BitmapFactory提供的加載圖片的四類方法(decodeFile、decodeResource、decodeStream、decodeByteArray)都支持BitmapFactory.Options參數==,通過inSampleSize參數就可以很方便地對一個圖片進行採樣縮放==
  • 比如一張10241024的高清圖片來說。那麼它佔有的內存爲102410244,即4MB,如果inSampleSize爲2,那麼採樣後的圖片佔用內存只有512512*4,即1MB(注意:根據最新的官方文檔指出==,inSampleSize的取值應該總是爲2的指數==,即1、2、4、8等等,如果外界輸入不足爲2的指數,系統也會默認選擇最接近2的指數代替,比如2)
  • 綜合考慮。通過採樣率即可有效加載圖片,==流程如下==
  1. 將BitmapFactory.Options的inJustDecodeBounds參數設爲true並加載圖片
  2. 從BitmapFactory.Options中取出圖片的原始寬高信息,它們對應outWidth和outHeight參數
  3. 根據採樣率的規則並結合目標View的所需大小計算出採樣率inSampleSize
  4. 將BitmapFactory.Options的inJustDecodeBounds參數設爲false,重新加載圖片。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章