在Android開發中,我現在發現很多人還不會對圖片占用內存進行很好的計算。
因此撰寫該博文來做介紹,期望達到拋磚引玉的作用。
Android中一張圖片(BitMap)占用的內存主要和以下幾個因數有關:圖片長度,圖片寬度,單位像素占用的字節數。
一張圖片(BitMap)占用的內存=圖片長度*圖片寬度*單位像素占用的字節數
注:圖片長度和圖片寬度的單位是像素。
圖片(BitMap)占用的內存應該和屏幕密度(Density)無關,雖然我暫時還拿不出直接證據。
創建一個BitMap時,其單位像素占用的字節數由其參數BitmapFactory.Options的inPreferredConfig變量決定。
inPreferredConfig為Bitmap.Config類型,Bitmap.Config類是個枚舉類型,它可以為以下值
Enum Values |
Bitmap.Config
ALPHA_8
Each pixel is stored as a single translucency (alpha) channel.
This is very useful to efficiently store masks for instance. No color information is stored.
With this configuration, each pixel requires 1 byte of memory.
此時圖片只有alpha值,沒有RGB值,
一個像素占用一個字節
Bitmap.Config
ARGB_4444
This field is deprecated. Because of the poor quality of this configuration,
it is advised to use ARGB_8888
instead.
這種格式的圖片,看起來質量太差,已經不推薦使用。
Each pixel is stored on 2 bytes. The three RGB color channels and the alpha channel (translucency)
are stored with a 4 bits precision (16 possible values.)
This configuration is mostly useful if the application needs to store translucency information
but also needs to save memory. It is recommended to use ARGB_8888 instead of this configuration.
一個像素占用2個字節,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占4個bites
共16bites,即2個字節
Bitmap.Config
ARGB_8888
Each pixel is stored on 4 bytes. Each channel (RGB and alpha for translucency)
is stored with 8 bits of precision (256 possible values.) This configuration
is very flexible and offers the best quality. It should be used whenever possible
一個像素占用4個字節,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占8個bites
共32bites,即4個字節
這是一種高質量的圖片格式,電腦上普通采用的格式。它也是Android手機上一個BitMap的默認格式。
Bitmap.Config
RGB_565
Each pixel is stored on 2 bytes and only the RGB channels are encoded:
red is stored with 5 bits of precision (32 possible values),
green is stored with 6 bits of precision (64 possible values) and blue
is stored with 5 bits of precision. This configuration can produce slight visual
artifacts depending on the configuration of the source. For instance,
without dithering, the result might show a greenish tint.
To get better results dithering should be applied.
This configuration may be useful when using opaque bitmaps that do not require high color fidelity.
一個像素占用2個字節,沒有alpha(A)值,即不支持透明和半透明,
Red(R)值占5個bites ,Green(G)值占6個bites ,Blue(B)值占5個bites,共16bites,即2個字節.
對於沒有透明和半透明顏色的圖片來說,該格式的圖片能夠達到比較的呈現效果,
相對於ARGB_8888來說也能減少一半的內存開銷。因此它是一個不錯的選擇。
另外我們通過android.content.res.Resources來取得一個張圖片時,它也是以該格式來構建BitMap的
從Android4.0開始,該選項無效。即使設置為該值,系統任然會采用 ARGB_8888來構造圖片
注:ARGB指的是一種色彩模式,裡面A代表Alpha,R表示red,G表示green,B表示blue,其實所有的可見色都是紅綠藍組成的,所以紅綠藍又稱為三原色。
A R G B
透明度 紅色 綠色 藍色
簡單點說
圖片格式(Bitmap.Config)
占用內存的計算方向
一張100*100的圖片占用內存的大小
ALPHA_8
圖片長度*圖片寬度
100*100=10000字節
ARGB_4444
圖片長度*圖片寬度*2
100*100*2=20000字節
ARGB_8888
圖片長度*圖片寬度*4
100*100*4=40000字節
RGB_565
圖片長度*圖片寬度*2
100*100*2=20000字節
另外,需要注意這裡的圖片占用內存是指在Navtive中占用的內存,當然BitMap使用的絕大多數內存就是該內存。
因為我們可以簡單的認為它就是BitMap所占用的內存。
Bitmap對象在不使用時,我們應該先調用recycle(),然後才它設置為null.
雖然Bitmap在被回收時可以通過BitmapFinalizer來回收內存。但是調用recycle()是一個良好的習慣
在Android4.0之前,Bitmap的內存是分配在Native堆中,調用recycle()可以立即釋放Native內存。
從Android4.0開始,Bitmap的內存就是分配在dalvik堆中,即JAVA堆中的,調用recycle()並不能立即釋放Native內存。但是調用recycle()也是一個良好的習慣。
通過dumpsys meminfo命令可以查看一個進程的內存使用情況,
當然也可以通過它來觀察我們創建或銷毀一張BitMap圖片內存的變化,從而推斷出圖片占用內存的大小。
示例:adb shell "dumpsys meminfo com.lenovo.robin"
運行結果。
Applications Memory Usage (kB):
Uptime: 18696550 Realtime: 18696541
** MEMINFO in pid 7985 [com.lenovo.robin] **
native dalvik other
total
size: 4828 5379 N/A 10207
allocated: 4073 2852 N/A 6925
free: 10 2527 N/A 2537
(Pss): 608 317 1603 2528
(shared dirty): 2240 1896 6056 10192
(priv dirty): 548 36 1276 1860
Objects
Views: 0 ViewRoots: 0
AppContexts: 0 Activities: 0
Assets: 2 AssetManagers: 2
Local Binders: 5 Proxy Binders: 11
Death Recipients: 1
OpenSSL Sockets: 0
SQL
heap: 0 MEMORY_USED: 0
PAGECACHE_OVERFLOW: 0 MALLOC_SIZE: 0