Android解决网络加载大图片OOM的问题

首先我们要获取网络上的图片,这里我们使用AndroidAPI中的HttpUrlConnection,具体代码如下:

private HttpURLConnection getHttpURLConnection(String imgUrl)throws Exception{
    URL url=new URL(imgUrl);
    HttpURLConnection httpURLConnection=(HttpURLConnection) url.openConnection();
    httpURLConnection.setConnectTimeout(10000);
    httpURLConnection.setRequestMethod("GET");
    httpURLConnection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9");
    httpURLConnection.setRequestProperty("Accept","*/*");
    return httpURLConnection;
}

类中的其他方法获取HttpUrlConnection并开启连接:

HttpURLConnection httpURLConnection=getHttpURLConnection(imgUrl);
httpURLConnection.connect();

获取图片输入流:

InputStream inputStream=httpURLConnection.getInputStream();
BufferedInputStream buffInputStream = new BufferedInputStream(inputStream);

在这里,我们解决图片OOM问题的方法是设置图片采样时的样本大小,即sampleSize。

这里打个比方,假如网络图片的宽高是1920*1080,这里我们设置样本大小sampleSize=n,那么网络图片的宽高都会除以n倍,即网络图片的宽高变为:(1920/n)*(1080/n)。通过这个方法,我们就可以将图片压缩来解决OOM的问题。

当然,sampleSize不应该被设置成固定值,我们应该让他按照原控件的大小来缩放相应的比例

假设我们用ImageView来存放图片,ImageView(img)宽高分别为800*600,网络图片(netImg)宽高分别为1920*1080,那么sampleSize的值就应该是两者宽的比和高的比取其中更大的那个比值

即:sampleSize=max( netImg.width / img.width , netImg.height / img.height )

具体代码如下:

private int getBitmapSampleSize(BitmapFactory.Options options,int measuredWidth,int measuredHeight){
    int outWidth=options.outWidth;
    int outHeight=options.outHeight;
    int sampleSize=1;
    //原图要大于控件大小,不然就没有必要压缩
    if(outHeight>measuredHeight||outWidth>measuredWidth){
        int btHeight=outHeight/measuredHeight;
        int btWidth=outWidth/measuredWidth;
        sampleSize=btHeight>btWidth?btHeight:btWidth;
    }
    return sampleSize;
}

下面贴出完整代码:

public class NetImageActivity extends AppCompatActivity{
    private ImageView img;
    private String imgUrl="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1586846404773&di=38a80a02ad991f77c610c52c661241d2&imgtype=0&src=http%3A%2F%2Fwww.baiyunshan.org.cn%2Fd%2Ffile%2Fnews%2Fgame%2F20190926%2Fcfd02160c79deeb5ce2f71c4b175b43a.jpg";
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.net_image_layout);
        initView();
        loadImg();
    }

    private void initView(){
        img=findViewById(R.id.img);
    }

    private void loadImg(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    HttpURLConnection httpURLConnection=getHttpURLConnection(imgUrl);
                    httpURLConnection.connect();
                    int responseCode=httpURLConnection.getResponseCode();
                    if(responseCode==HttpURLConnection.HTTP_OK){
                        InputStream inputStream=httpURLConnection.getInputStream();
                        BufferedInputStream buffInputStream = new BufferedInputStream(inputStream);
                        BitmapFactory.Options options=new BitmapFactory.Options();
                        //不加载图片到内存
                        options.inJustDecodeBounds=true;

                        //对buffInputStream进行重复利用
                        buffInputStream.mark(0);
                        BitmapFactory.decodeStream(buffInputStream,null,options);
                        buffInputStream.reset();

                        options.inSampleSize=getBitmapSampleSize(options,img.getMeasuredWidth(),img.getMeasuredHeight());
                        //这里要设为false,否则图片无法加载到内存
                        options.inJustDecodeBounds=false;
                        final Bitmap bitmap=BitmapFactory.decodeStream(buffInputStream,null,options);
                        buffInputStream.close();
                        inputStream.close();
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                img.setImageBitmap(bitmap);
                            }
                        });
                    }
                    httpURLConnection.disconnect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private HttpURLConnection getHttpURLConnection(String imgUrl)throws Exception{
        URL url=new URL(imgUrl);
        HttpURLConnection httpURLConnection=(HttpURLConnection) url.openConnection();
        httpURLConnection.setConnectTimeout(10000);
        httpURLConnection.setRequestMethod("GET");
        httpURLConnection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9");
        httpURLConnection.setRequestProperty("Accept","*/*");
        return httpURLConnection;
    }

    private int getBitmapSampleSize(BitmapFactory.Options options,int measuredWidth,int measuredHeight){
        int outWidth=options.outWidth;
        int outHeight=options.outHeight;
        int sampleSize=1;
        //原图要大于控件大小,不然就没有必要压缩
        if(outHeight>measuredHeight||outWidth>measuredWidth){
            int btHeight=outHeight/measuredHeight;
            int btWidth=outWidth/measuredWidth;
            sampleSize=btHeight>btWidth?btHeight:btWidth;
        }
        return sampleSize;
    }
}

 

你可能感兴趣的:(Android)