在Android應用裏,最耗費內存的就是圖片資源。而且在Android系統中,讀取位圖Bitmap時,分給虛擬機中的圖片的堆棧大小隻有8M,如果超出了,就會出現OutOfMemory異常。所以,對於圖片的內存優化,是Android應用開發中比較重要的內容。
我們去解析一個圖片,如果太大,就會OOM,我們可以設置壓縮比例inSampleSize,但是這個壓縮比例設置多少就是個問題,所以我們解析圖片可以分爲倆個步驟,第一步就是獲取圖片的寬高,這裏要設置Options.inJustDecodeBounds=true,這時候decode的bitmap爲null,只是把圖片的寬高放在Options裏,然後第二步就是設置合適的壓縮比例inSampleSize(本文的壓縮比例計算,計算遠程圖片的大小然後開平方根,將計算的結果作爲縮小比例),這時候獲得合適的Bitmap.簡單的流程圖,如下:
Bitmap bmImg = null;
URL myFileUrl = null;
private byte[] bytes;
private InputStream is;
public Bitmap loadBitmap(String url) {
try {
myFileUrl = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
Log.e(TAG, " new URL error: " + url);
return null;
}
//=======1.按一般流程讀取遠程圖片,保存爲Bitmap
try {
HttpURLConnection conn = (HttpURLConnection) myFileUrl
.openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setDoInput(true);conn.connect();
is = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = is.read(b, 0, 1024)) != -1) {
baos.write(b, 0, len);
baos.flush();
}
bytes = baos.toByteArray();
bmImg = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
is.close();
} catch (IOException e) {
Log.e(TAG, "loadBitmap error1: " + e.toString());
bmImg = null;
e.printStackTrace();
}catch(OutOfMemoryError error){
Log.e(TAG, "loadBitmap error2: " + error.toString());
//=======2.捕獲到OutOfMemoryError 異常時,重新加載
bmImg=getBitmap(myFileUrl);
return bmImg;
}
return bmImg;
}
private Bitmap getBitmap(URL url) {
//=======3.第一次讀取圖片,獲取圖片的寬高
try {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setDoInput(true);
conn.connect();
is = conn.getInputStream();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//****
bmImg = BitmapFactory.decodeStream(is, null, options);
int picWidth = options.outWidth; //圖片寬度
int picHeight = options.outHeight;//圖片高度
Log.d(TAG, "==width=="+picWidth+"==height=="+picHeight);
if(picWidth==-1||picWidth==-1)
return null;
//根據遠程圖片的寬高計算資源文件的大小,然後取大小的平方根,將結果作爲縮放倍數
int date = (int)Math.sqrt(picHeight/1024*picWidth/1024*4);
//=======4.根據圖片的大小,比例縮小圖片
bmImg=getBitmap2(url, date);
} catch (IOException e) {
e.printStackTrace();
}
return bmImg;
}
private Bitmap getBitmap2(URL url, int date) {
BitmapFactory.Options options = null;
Bitmap bitmap = null;
try {
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setDoInput(true);
conn.connect();
is = conn.getInputStream();
options=new BitmapFactory.Options();
options.inSampleSize=date;//*****
options.inJustDecodeBounds=false;//****
bitmap=BitmapFactory.decodeStream(is, null, options);
is.close();
return bitmap;
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}