zoukankan      html  css  js  c++  java
  • Android异步载入全解析之大图处理

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

    异步载入中很重要的一部分就是对图像的处理,这也是我们前面用异步载入图像做示例的原因。

    一方面是由于图像处理不好的话会很占内存,并且easyOOM,还有一方面,图像也比文字要大,载入比較慢。所以,在解说了怎样进行多线程、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; }


    方法很easy。就是通过期望长宽来获取缩放的比例。以下我们就创建一个方法来获取缩放后的图像。这里为了演示,我们仅仅创建从资源文件里获取图像的方法:

    /**
     * 使用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这样一个方法,我们就能够很easy的将图像进行压缩。



    我的Github
    我的视频 慕课网







  • 相关阅读:
    为什么需要Docker?
    一分钟学会《模板方法模式》
    2018再见|2019你好
    三分钟学会《门面模式》
    策略模式原来这么简单!
    外行人都能看得懂的机器学习,错过了血亏!
    我是如何将博客转成PDF的
    面试前必须知道的MySQL命令【explain】
    count(*)、count(1)和count(列名)的区别
    Linux shell去除字符串中所有空格
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6786247.html
Copyright © 2011-2022 走看看