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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章