安卓加载网络图片OOM问题解决
前言:次片是上篇后续出现的问题,在网上找了很多博客,越解决越乱,好在最后看了郭霖的博客给了我一点思路
借鉴:http://blog.csdn.net/guolin_blog/article/details/9316683
请仔细阅读这边博客的说明部分,不要急着看代码(这也是我一贯的做法,其实有时候把说明部分多读读能快速理解代码的意思,事半功倍)
代码:
/** * 获取网络图片(需要开线程) * @param url * @return */ public static void getHttpBitmap(final int position, final String url){ new Thread(new Runnable() { @Override public void run() { try{ URL myUrl; Bitmap bitmap = null; myUrl = new URL(url); //获得连接 HttpURLConnection conn = (HttpURLConnection)myUrl.openConnection(); //设置超时时间为6000毫秒,conn.setConnectionTiem(0);表示没有时间限制 conn.setConnectTimeout(6000); //连接设置获得数据流 conn.setDoInput(true); //不使用缓存 conn.setUseCaches(false); //此方法用于在预先不知道内容长度时启用没有进行内部缓冲的 HTTP请求正文的流 conn.setChunkedStreamingMode(51200); // 128K //这句可有可无,没有影响 //conn.connect(); //得到数据流 InputStream is = conn.getInputStream(); if (is != null){ BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; byte [] data = inputStream2ByteArr(is); BitmapFactory.decodeByteArray(data,0,data.length,options); options.inSampleSize = calculateInSampleSize(options,146,146); options.inJustDecodeBounds = false; //解析得到图片 bitmap = BitmapFactory.decodeByteArray(data,0,data.length,options); // EventBus EventBus.getDefault().post(new MyEventBus(MyEventBus.EVENT_CREATE_BITMAP,position,bitmap)); //可以注释掉,请不要在意这部分,这里是通过EventBus将bitmap传递个Activity,读者测试可用Handle, } //关闭数据流 is.close(); }catch(Exception e){ e.printStackTrace(); } } }){}.start(); } /** * 输入流转成字节数组(重复读取) * @param inputStream * @return * @throws IOException */ public static byte[] inputStream2ByteArr(InputStream inputStream) throws IOException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buff = new byte[1024]; int len = 0; while ( (len = inputStream.read(buff)) != -1) { outputStream.write(buff, 0, len); } inputStream.close(); outputStream.close(); return outputStream.toByteArray(); } /** * 计算options.InSampleSize值 此算法可根据需求改动 * @param options * @param reqWidth 期望宽 * @param reqHeight 期望高 * @return */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // 源图片的高度和宽度 final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { // 计算出实际宽高和目标宽高的比率 final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高 // 一定都会大于等于目标的宽和高。 inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; }
注意几点:
1、(郭霖博客中)
options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
设置为true 时,返回的BitMap 将为 Null
2、读取网络图片用的是decodeStream,但是此处却不能直接这样用,为何,这里总共会读取两次,而第二次读的时候流已经改变,所以最后一次读取的是null,这里用字节数组存储流,以后可以多次使用
这里在推荐一遍博客:https://blog.csdn.net/xiejc01/article/details/17421957