国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android開發中Bitmap高效加載使用詳解

2019-10-22 18:20:33
字體:
來源:轉載
供稿:網友

由于Android對單個應用所施加的內存限制,比如16MB,這導致加載Bitmap的時候很容易出現內存溢出,本文主要包含2個方面的內容分析Bitmap內存和Bitmap高效加載

一、占用內存

獲取bitmap的內存,android提供的方法bitmap.getByteCount()
假如現在mipmap-xhdpi 目錄下,有一個 200 * 200 像素的圖片,運行加載它,看它輸出的尺寸。

Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.mipmap.btn_go);
bitmap.getByteCount()的輸出結果為360000
現在把圖片轉移到mipmap-xxhdpi 中
bitmap.getByteCount的輸出結果為160000
那么mipmap-xhdpi 目錄下為何會大這么多呢?

density 影響 Bitmap 內存
放在不同的 mipmap 目錄下,對應的不同 density 的設備。density 是設備的固有參數,伴隨著 density 的,還有 densityDpi,它也是與設備相關的,表示屏幕每英寸對應多少個點(非像素點)

高效,加載,bitmap,Android,Bitmap加載

上面是官方提供的一張比較經典的圖,可以看到,不同的目錄,代表不同的 density ,例如 xhdpi 代表的 density 就是 2。而這里的 density 對 densityDip 的基準是 160 ,也就是說,mdpi 對應的 densityDpi 是 160 ,xhdpi 對應的 densityDpi 是 320,同樣xxhdpi對應的densityDpi是480

density 和 densityDpi 在 Android 中,都有標準的 API 可以拿到,如下。

DisplayMetrics displayMetrics=new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);Log.i(TAG, displayMetrics.densityDpi+"");Log.i(TAG,displayMetrics.density+"");

這是我手機的輸出結果

densityDpi:480density:3.0

從getByteCount()源碼得知,Bitmap.getByteCount() 是由:
(bitmapWidth * scale) * (bitmapHeight * scale) *(每像素所占字節大小)得出來的
其中:int scale = phoneDensity / inDensity
phoneDensity是我們手機的densityDpi,上述得出我手機是480
inDensity是你圖片存放的路徑,比如xhdpi是320,xxhdpi是480
BitmapFactory默認色彩度為 ARGB_8888 圖片,每像素會占用 4 bytes
在xhdpi下:200 * (480/320) * 200(480/320)4= 360000
在xxhdpi下:200 * (480/480) * 200(480/480)4= 160000

以上就是bitmap所占內存分析。

二、高效加載

1.修改bitmap.config
2.修改inSampleSize

bitmap.config簡介

上面提到BitmapFactory默認色彩度為 ARGB_8888

Bitmap.Config一共有四個參數如下:
(這些參數決定了Bitmap位圖的配置,會影響到bitmap的像素如何、色彩、以及是否有透明度的能力)

Bitmap.Config ALPHA_8

這個參數每個像素占用1字節的空間。
它代表每個像素點被存儲為單個透明度的通道,這對于設置遮罩的圖片用例十分有用,它不存儲顏色信息。

Bitmap.Config RGB_565

這個參數每個像素占用2字節的空間。
它代表只有RGB通道的編碼,其中紅色占用5位地址,綠色占用6位地址,藍色占用5位地址。沒有透明度的通道。
使用不透明的位圖時,不要求高的色彩保真度使用此配置是不錯的選擇。

Bitmap.Config ARGB_4444

這個參數每個像素占用2字節的空間。
它一共有四個通道,顧名思義,分別是透明度、紅、綠、藍。每個通道分別占用四位地址,所以一共2字節。
當應用需要節省內存(對色彩質量要求低),同時又需要存儲透明度信息,這個配置可以作為選擇,但官方比較推薦用ARGB_8888的設置,因為這個的色彩質量差。

Bitmap.Config ARGB_8888

這個參數每個像素占用4字節的空間。
這也是一共4個通道,但不一樣的是每個通道站8位地址,因而色彩質量比上一個設置高了特別特別多(16倍)。
能夠滿足最好的位圖質量,在內存充足的情況下,十分推薦使用這個。

inSampleSize簡介

通過BitmapFactory.Options來縮放圖片,主要是用inSampleSize參數,當inSampleSize=1時,采樣后的圖片為圖片的原始大小,當inSampleSize=2時,采樣后的圖片寬,高均為原圖大小的1/2,而像素數為原圖的1/4,假定圖片原有的內存是4MB,如果把它的inSampleSize設為2,它的內存就會變成1MB
具體實現代碼如下

 public static Bitmap decodeBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight){  final BitmapFactory.Options options=new BitmapFactory.Options();  options.inJustDecodeBounds=true;  BitmapFactory.decodeResource(res,resId,options);  options.inSampleSize=1;  options.inSampleSize=setInSampleSize(options,reqWidth,reqHeight);  options.inPreferredConfig= Bitmap.Config.ARGB_4444;  options.inJustDecodeBounds=false;  return BitmapFactory.decodeResource(res,resId,options); } public static int setInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){  final int height=options.outHeight;  final int width=options.outWidth;  int inSampleSize=1;  if(height>reqHeight||width>reqHeight){   final int halfHeght=height/2;   final int halfWidht=width/2;   while ((halfHeght/inSampleSize>=reqHeight)&&(halfWidht/inSampleSize>=reqWidth)){    inSampleSize *=2;   }  }  return inSampleSize; }

有了上面兩個方法,實際使用就簡單了,比如imageView所期望的圖片大小為100X100,這個時候我們就可以這樣調用,還是之前存放在xxhdpi中的圖片,上述代碼中已經把bitmap.config設置成ARGB_4444 ,現在把原先尺寸200X200改成100X100,看下內存是多少

Bitmap bitmap=decodeBitmapFromResource(getResources(),R.mipmap.btn_go,100,100);Log.i(TAG,bitmap.getByteCount()+"");

bitmap.getByteCount的輸出結果為20000,比之前160000減少了8倍, ARGB_4444較ARGB_8888減少了2倍,設置尺寸100,100傳入setInSampleSize()方法中得到inSampleSize=2, 像素數為原圖的1/4,內存大小總共就變成了之前的1/8,這樣高效加載圖片,就會遠離oom。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黎平县| 沭阳县| 黄石市| 益阳市| 紫阳县| 天台县| 沁阳市| 清涧县| 阿克苏市| 炎陵县| 松原市| 孙吴县| 屏东县| 邛崃市| 荣昌县| 顺平县| 嵩明县| 吉木萨尔县| 和龙市| 太仓市| 孟州市| 泽州县| 北海市| 封丘县| 明水县| 牙克石市| 平潭县| 鄯善县| 宁国市| 合江县| 乐陵市| 济阳县| 贺州市| 安丘市| 北海市| 金寨县| 石台县| 兰溪市| 开封市| 永登县| 务川|