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