APP效能最佳化系列:記憶體最佳化-bitmap詳解

來源:互聯網
上載者:User

標籤:

??在Android應用開發中,我們經常需要跟圖片打交道,而圖片一個很麻煩的問題是佔用記憶體非常大,經常導致OOM,瞭解Bitmap相關資訊,不同sdk版本中Android圖片處理的變化,以及一些最佳化處理的方式對我們平時開發中對圖片的會非常有協助。

??在開始本節的內容之前我們.先來區分幾個名詞的概念:

  • Drawable:通用的繪圖物件,用於裝載常用格式的映像,既可以是PNG,JPG這樣的映像, 也是前面學的那13種Drawable類型的可視化對象!我們可以理解成一個用來放畫的——畫框!

  • Bitmap(位元影像):我們可以把他看作一個畫架,我們先把畫放到上面,然後我們可以 進行一些處理,比如擷取影像檔資訊,做旋轉切割,放大縮小等操作!

  • Canvas(畫布):如其名,畫布,我們可以在上面作畫(繪製),你既可以用Paint(畫筆), 來畫各種形狀或者寫字,又可以用Path(路徑)來繪製多個點,然後串連成各種圖形!

  • Matrix(矩陣):用於圖形特效處理的,顏色矩陣(ColorMatrix),還有使用Matrix進行映像的平移,縮放,旋轉,傾斜等!

一.bitmap相關api

瞭解Bitmap,BitmapFactory,BitmapFacotry.Options

1.Bitmap

bitmap常見方法:

普通方法public boolean compress (Bitmap.CompressFormat format, int quality, OutputStream stream) 將位元影像的壓縮到指定的OutputStream,可以理解成將Bitmap儲存到檔案中! format:格式,PNG,JPG等; quality:壓縮品質,0-100,0表示最低畫質壓縮,100最大品質(PNG無損,會忽略品質設定) stream:輸出資料流 傳回值代表是否成功壓縮到指定流!void recycle():回收位元影像佔用的記憶體空間,把位元影像標記為Deadboolean isRecycled():判斷位元影像記憶體是否已釋放int getWidth():擷取位元影像的寬度int getHeight():擷取位元影像的高度boolean isMutable():圖片是否可修改int getScaledWidth(Canvas canvas):擷取指定密度轉換後的映像的寬度int getScaledHeight(Canvas canvas):擷取指定密度轉換後的映像的高度靜態方法:Bitmap createBitmap(Bitmap src):以src為原圖產生不可變得新映像Bitmap createScaledBitmap(Bitmap src, int dstWidth,int dstHeight, boolean filter):以src為原圖,建立新的映像,指定新映像的高寬以及是否變。Bitmap createBitmap(int width, int height, Config config):建立指定格式、大小的位元影像Bitmap createBitmap(Bitmap source, int x, int y, int width, int height)以source為原圖,建立新的圖片,指定起始座標以及新映像的高寬。public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
2.BitmapFactory

??Bitmap的構造方法是私人的,外面不能執行個體化,只能通過JNI執行個體化! 當然,肯定也會給我們提供一個介面給我們來建立Bitmap的,而這個介面類就是:BitmapFactory! 來來來,開啟BitmapFactory類,我們點下左邊的Structure可以看到BitmapFactory給我們 提供了這些方法,大部分都是decodeXxx,通過各種形式來建立Bitmap的!

3.BitmapFacotry.Options

??接著我們又發現了,每一種方法,都會有一個Options類型的參數,點進去看看: 於是乎我們發現了這貨是一個靜態內部類:BitmapFacotry.Options! 而他是用來設定decode時的選項的!

我們對這裡的某些參數的值進行設定,比如inJustDecodeBounds設定為true避免OOM(記憶體溢出).

常見的設定:

boolean inJustDecodeBounds——如果設定為true,不擷取圖片,不分配記憶體,但會返回圖片的高寬度資訊。int inSampleSize——圖片縮放的倍數。如果設為4,則寬和高都為原來的1/4,則圖是原來的1/16。int outWidth——擷取圖片的寬度值int outHeight——擷取圖片的高度值int inDensity——用於位元影像的像素壓縮比int inTargetDensity——用於目標位元影像的像素壓縮比(要產生的位元影像)boolean inScaled——設定為true時進行圖片壓縮,從inDensity到inTargetDensity。
二.bitmap佔用的記憶體大小如何計算

結論:
一張 ARGB_8888 的 Bitmap 佔用記憶體的計算公式:
bitmapInRam = bitmapWidth*bitmapHeight *4 bytes

我們讀取的是 drawable 目錄下面的圖片,用的是 decodeResource 方法,系統在讀取這些目錄下的圖片時會對圖片進行縮放,這也是需要考慮的。

Bitmap 在記憶體當中佔用的大小其實取決於:
色彩格式,前面我們已經提到,如果是 ARGB8888 那麼就是一個像素4個位元組,如果是 RGB565 那就是2個位元組
原始檔案存放的資來源目錄(是 hdpi 還是 xxhdpi 可不能傻傻分不清楚哈)
目標螢幕的密度(所以同等條件下,紅米在資源方面消耗的記憶體肯定是要小於三星S6的)

關於ARGB_8888、ALPHA_8、ARGB_4444、RGB_565的理解

A:透明度

R:紅色

G:綠

B:藍

Bitmap.Config ARGB_4444:每個像素佔四位,即A=4,R=4,G=4,B=4,那麼一個像素點佔4+4+4+4=16位

Bitmap.Config ARGB_8888:每個像素佔四位,即A=8,R=8,G=8,B=8,那麼一個像素點佔8+8+8+8=32位

Bitmap.Config RGB_565:每個像素佔四位,即R=5,G=6,B=5,沒有透明度,那麼一個像素點佔5+6+5=16位

Bitmap.Config ALPHA_8:每個像素佔四位,只有透明度,沒有顏色。

一般情況下我們都是使用的ARGB_8888,由此可知它是最占記憶體的,因為一個像素佔32位,8位=1位元組,所以一個像素佔4位元組的記憶體。假設有一張480x800的圖片,如果格式為ARGB_8888,那麼將會佔用1500KB的記憶體。

三.android的底層圖片庫

底層使用的是Skia庫、libJpeg庫。

http://www.cnblogs.com/hrlnw/p/4403334.html

http://www.kuqin.com/shuoit/20140826/341828.html?url_type=39&object_type=crawler&pos=1

四.android巨圖載入方案

巨圖載入,當然不能使用常規方法,必OOM。原理比較簡單,系統中有一個類BitmapRegionDecoder。有個第三方可借鑒SubsamplingScaleImageView。

http://www.lai18.com/content/6705664.html

五.Android載入不同DPI資源與記憶體消耗間的關係

http://www.tinylab.org/android-loading-a-different-relationship-between-dpi-and-memory-consumption-of-resources/

參考資料

Android Bitmap Api總結和使用方法
http://blog.csdn.net/shell812/article/details/49781255

Android中圖形圖片及處理相關Api的小總結
http://blog.csdn.net/zjngogo/article/details/49665113

API Demo學習——android Bitmap學習總結
http://blog.sina.com.cn/s/blog_5da93c8f0100w3xz.html

Bitmap(位元影像)全解析 Part 1
http://www.kancloud.cn/kancloud/android-tutorial/87244

Android 開發繞不過的坑:你的 Bitmap 究竟佔多大記憶體?
https://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=403263974&idx=1&sn=b0315addbc47f3c38e65d9c633a12cd6&scene=0&key=41ecb04b0511100390dcd25b8d443be2a357c0de12cdba7e7b1c4d06e1c2a9331881b1697239b4a3b89b86ef42a7eba9&ascene=0&uin=MTYzMjY2MTE1&devicetype=iMac+MacBookPro10,1+OSX+OSX+10.11.2+build(15C50)&version=11020201&pass_ticket=9p5lnIh3K3G8I2FvfncYkoGNOueUiq1+6ELLdgUwkGc=

Android 載入不同 DPI 資源與記憶體消耗間的關係
http://www.tinylab.org/android-loading-a-different-relationship-between-dpi-and-memory-consumption-of-resources/

Android Bitmap面面觀
https://mp.weixin.qq.com/s?__biz=MzA4MjU5NTY0NA==&mid=404530070&idx=1&sn=e2580b69d6ec73dabf8160216aa6702a&scene=1&srcid=0322dGvv5B4miLg3vt0q2rK2&key=710a5d99946419d9e5ab07eaa09e546952524b770e8a63c46c223b7588209d3a542fe4a0827571ac73b03cb78b404289&ascene=0&uin=MTYzMjY2MTE1&devicetype=iMac+MacBookPro10,1+OSX+OSX+10.11.4+build(15E65)&version=11020201&pass_ticket=Sqb+pOLTrZ0wixoScJ8flYxFV4tOFnBa7NFos1uIG8U=

http://m.blog.csdn.net/article/details?id=7856519

APP效能最佳化系列:記憶體最佳化-bitmap詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.