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;
	}

你可能感兴趣的:(android,图片)