加载长图问题与解决方案

长图加载问题总结

前言

如果RecycleView或者listview的item中有IamgeView。小图片还好,如果图片过长或者过大就会出现加载不出、OOM这样的问题。
解决的方法也很简单:

  • 压缩图片
  • 自定义控件支持大图显示

压缩图片

BitMap基本信息

一张图片在内存中占用
图片长度 x 图片宽度 x 一个像素点占用的字节数

其中,A代表透明度;R代表红色;G代表绿色;B代表蓝色。

  • ALPHA_8
    表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度

  • ARGB_4444
    表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节

  • ARGB_8888
    表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节

  • RGB_565
    表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节

压缩质量

(它是在保持像素的前提下改变图片的位深及透明度)(不能用了压缩PNG格式图片)

  • bitmap.compress(CompressFormat.JPEG, quality, baos);

采样率压缩

(inJustDecodeBounds设置为true的时候,BitmapFactory通过decodeResource或者decodeFile解码图片时,将会返回空(null)的Bitmap对象,这样可以避免Bitmap的内存分配,但是它可以返回Bitmap的宽度、高度以及MimeType)

BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2;

        bm = BitmapFactory.decodeFile(Environment
                .getExternalStorageDirectory().getAbsolutePath()
                + "/DCIM/Camera/test.jpg", options);
        Log.i("wechat", "压缩后图片的大小" + (bm.getByteCount() / 1024 / 1024)
                + "M宽度为" + bm.getWidth() + "高度为" + bm.getHeight());

缩放法压缩(martix)

Matrix matrix = new Matrix();
        matrix.setScale(0.5f, 0.5f);
        bm = Bitmap.createBitmap(bit, 0, 0, bit.getWidth(),
                bit.getHeight(), matrix, true);
        Log.i("wechat", "压缩后图片的大小" + (bm.getByteCount() / 1024 / 1024)
                + "M宽度为" + bm.getWidth() + "高度为" + bm.getHeight());

RGB_565图片显示格式

BitmapFactory.Options options2 = new BitmapFactory.Options();
        options2.inPreferredConfig = Bitmap.Config.RGB_565;

        bm = BitmapFactory.decodeFile(Environment
                .getExternalStorageDirectory().getAbsolutePath()
                + "/DCIM/Camera/test.jpg", options2);
        Log.i("wechat", "压缩后图片的大小" + (bm.getByteCount() / 1024 / 1024)
                + "M宽度为" + bm.getWidth() + "高度为" + bm.getHeight());

createScaledBitmap

(这里是将图片压缩成用户所期望的长度和宽度,但是这里要说,如果用户期望的长度和宽度和原图长度宽度相差太多的话,图片会很不清晰。)

bm = Bitmap.createScaledBitmap(bit, 150, 150, true);
        Log.i("wechat", "压缩后图片的大小" + (bm.getByteCount() / 1024) + "KB宽度为"
                + bm.getWidth() + "高度为" + bm.getHeight());

上面是原理,但是一般不会让前段去压缩。将图片上传到后台,进行压缩显示。前段显示的时候一般也会再次进行压缩显示的。一般Glide或者第三方图片加载库都会进行压缩配置。

这里特别说明的是长图的压缩显示:

  • 长图的宽一般是适配屏幕的建议压缩到720像素
  • 长图的长根据宽的比例进行压缩公式:长=原图长宽比*720

自定义控件显示长图

为什么不用系统的ImageView:
因为系统的ImageView根据手机不同只能显示2048*2048或者4096*4096像素大小的图片。 (确切的说是ImageView里的Canves画布只能显示那么大的像素)

推荐长图显示控件

https://github.com/davemorrissey/subsampling-scale-image-view

使用方法

配置

compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.7.2'

代码

SubsamplingScaleImageView imageView = new SubsamplingScaleImageView(PostDetailActivityy.this);
//debug模式
imageView.setDebug(true);
//支持图片缩放
imageView.setZoomEnabled(true);
//设置图片配置信息
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
lp.setMargins(ConvertUtils.dp2px(0), ConvertUtils.dp2px(5), ConvertUtils.dp2px(0), ConvertUtils.dp2px(5));
imageView.setLayoutParams(lp);
Glide.with(PostDetailActivityy.this)
        .load(mPostDetailBean.getThumbnail_image().get(i).getThumbnail_image())
        .asBitmap()
        .diskCacheStrategy(DiskCacheStrategy.SOURCE)
        .into(new SimpleTarget() {
            @Override
            public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {                  
                imageView.setImage(ImageSource.bitmap(resource));
            }
        });
//设置监听事件
imageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
           //tudo
    }
});

你可能感兴趣的:(android开发)