Android 遠程圖片Bitmap進行展示時,OutOfMemory

在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;
	}
發佈了26 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章