安卓加载网络图片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

 

posted @ 2018-06-07 14:08  임문  阅读(372)  评论(0编辑  收藏  举报