Android异步加载全解析之大图处理

异步加载中非常重要的一部分就是对图像的处理,这也是我们前面用异步加载图像做演示例子的原因。一方面是因为图像处理不好的话会非常占内存,而且容易OOM,另一方面,图像也比文字要大,加载比较慢。所以,在讲解了如何进行多线程、AsyncTask进行多线程加载后,先暂停下后面的学习,来对图像的异步处理进行一些优化工作。

为什么要对图像处理

为什么要对图像进行处理,这是一个很直接的问题,一张图像,不管你拿手机、相机、单反还是什么玩意拍出来,它就有一定的大小,但是在不同的终端上,终端也有不同的大小,比如一张超高请无码大图,10M大小,在网页中看着挺爽,全高清,毛孔都看得清。同样一张图片,如果放在4.7寸的手机上,当然,同样还是一张高清无码大图,但这张图片10M,在电脑上可能不算什么,但在手机上,已经是非常大了,而这张图片在手机上,你拼命看,也就是那样,即使分辨率减少一半,你看上去也还是差不多。这就像所谓的视网膜屏、2k屏、4k屏,其实已经基本达到视觉分析的极限了,普通情况下,差别并不大。 但是,虽然你看着区别不大,但对系统来说,差别就非常大了,手机的内存,要像使用你藏的私房钱一样,每一分都要三思而用。所以,我们在下载高分辨率的图片的时候,可以对图像进行压缩,显示上虽然没有太大区别,但是却帮系统节省了大量的私房钱。

BitmapFactory之inSampleSize

BitmapFactory是Android中提供的对图像的解析方法,通过它的一些静态方法,我们可以对图像进行解析,例如从文件中解析——decodeFile;从资源中解析——decodeResource;从网络中解析——decodeStream等等。 当我们从网络上进行图像下载的时候,看情况,是否需要对图像进行压缩,那么如何在系统不加载图像到内存之前,就获取图像的大小等参数呢?看上去非常矛盾,但系统给我们提供了一种简单的解决方法。 BitmapFactory提供了BitmapFactory.Options参数,这个参数有一个inJustDecodeBounds属性,当这个属性为true的时候,我们就可以禁止系统加载图像到内存,但是!!!这时候,Options参数中的图像宽高、类型等属性已经被赋值了,这样,我们就实现了空手套白狼,哦,不对,是不使用内存就获取图像的属性。
BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(getResources(), R.id.myimage, options);// 获取属性值int imageHeight = options.outHeight;int imageWidth = options.outWidth;String imageType = options.outMimeType;

在获得了图像的参数之后,我们就可以对图像进行相应的处理了,例如我们显示图像的ImageView只有200 X 200 像素,而我们的图片有800 X 800 像素,那你把这么大的一张图放到这么小的ImageView中,有啥用呢?白白浪费了内存。OK,那么下面我们就来对图像进行压缩,Options参数中给我们提供了这样一个属性——inSampleSize,这个属性可以设置图像的缩放比例,例如一张1000 X 1000像素的图像,设置inSampleSize为5,意思就是把这个图像缩放到了五分之一,即200 X 200 。OK,下面我们就通过这样一个方法来对图像进行优化,首先,我们需要创建一个方法来获取到一个合适的inSampleSize:
/** * 获取合适的inSampleSize * @param options * @param targetWidth 期望Width * @param targetHeight 期望Height * @return */public static int getInSampleSize(BitmapFactory.Options options,                                        int targetWidth, int targetHeight) {    // 原始图片的高度和宽度    final int height = options.outHeight;    final int width = options.outWidth;    int inSampleSize = 1;    if (height > targetHeight || width > targetWidth) {        // 计算出实际宽高和目标宽高的比率        final int heightRate = Math.round((float) height / (float) targetHeight);        final int widthRate = Math.round((float) width / (float) targetWidth);        inSampleSize = heightRate < widthRate ? heightRate : widthRate;    }    return inSampleSize;}

方法非常简单,就是通过期望长宽来获取缩放的比例。下面我们就创建一个方法来获取缩放后的图像,这里为了演示,我们只创建从资源文件中获取图像的方法:
/** * 使用targetWidth、targetHeight来获取合适的inSampleSize * 并使用inSampleSize来缩放得到合适大小的图像 * @param res getResources() * @param resId id * @param targetWidth * @param targetHeight * @return */public static Bitmap decodeSuitableBitmap(Resources res, int resId,                                          int targetWidth, int targetHeight) {    // 空手套白狼    final BitmapFactory.Options options = new BitmapFactory.Options();    options.inJustDecodeBounds = true;    BitmapFactory.decodeResource(res, resId, options);    // 计算合适的inSampleSize    options.inSampleSize = getInSampleSize(options, targetWidth, targetHeight);    // 加载到内存    options.inJustDecodeBounds = false;    return BitmapFactory.decodeResource(res, resId, options);}

通过调用decodeSuitableBitmap这样一个方法,我们就可以非常简单的将图像进行压缩。


我的Github
我的视频慕课网







更多相关文章

  1. 在Android中,如何判断当前是否在桌面上
  2. Android获取手机WiFi IP地址,MAC地址和网关地址程序实例
  3. 关于Android(安卓)Matrix pre post 的理解
  4. android解析xml文件的方式之DOM解析
  5. [Android]你不知道的Android进程化(1)--进程信息
  6. OpenCV之Mat与Bitmap之间的转换
  7. android动态加载资源
  8. Android(安卓)进阶——高级UI必知必会之常用的自定义ViewGroup进
  9. android 扫码设备获取扫码回调内容实践

随机推荐

  1. Android(安卓)四大组件(Activity、Servic
  2. Android(安卓)Fragment 体系 源码追踪笔
  3. Android提高十七篇之多级树形菜单的实现
  4. Android开发获得多媒体信息
  5. 自定义模态提示框
  6. Android查看内存使用的方式(Running servi
  7. Android(安卓)Service的使用
  8. TextView字体加粗 ---Android基础篇——
  9. Android——自定义控件(一)
  10. 设置Android(安卓)Studio工程布局文件的