Android高效开发(一)—合理使用图片资源

前言

在Android开发中,咱们不免会遇到加载图片的场景。不论是网络图片、资源图片或者是SD卡中的图片,都须要加载到内存中使用。若是不能合理处理图片,可能会致使OOM的问题或者其余性能问题,接下就讨论下Android中图片资源处理的几种经常使用的方式。android

Resource中的图片资源的处理

在Android中开发的时候都会用到不少图片素材,对于某些背景图片、各类图标或者其余一些提示图片咱们一般会放到res目录中的drawable中。缓存

咱们知道在res目录下有不少drawable目录,好比:drawable、drawable-hdpi、drawable-mdpi等。这些目录对应了不一样密度的屏幕,在不一样密度的屏幕下会优先从对应目录下取图片资源。网络

目录名称 密度(Density)
res/drawable 0
res/drawable-ldpi 120
res/drawable-mdpi 160
res/drawable-hdpi 240
res/drawable-xhdpi 320
res/drawable-xxdpi 480

这六种目录表明了目前市面上Android机型不一样的6中密度的屏幕。框架

注意:res/drawable目录的密度为0,不是说有机型的屏幕密度为0。这是默认密度,在不一样机型下默认密度不同。ide

Android如何找到res中图片资源

Android在加载资源图片时,会先获取当前设备的屏幕密度,而后根据屏幕密度去找图片资源。若是没有在对应的文件夹下找到图片资源,就会采起就近原则,从与屏幕密度最相近的图片资源目录获取。若是都没有就只能从默认的资源目录下获取(也就是res/drawable)。性能

在获取到图片资源时,若是密度不匹配,Android会对图片进行处理。好比在res/drawable-mdpi找到了图片,可是设备屏幕密度是xxdpi的,那么Android就会按照3倍大小缩放这张图片。根据图片内存的计算公式(图片高度 x 图片宽度 x 一个像素占用的内存大小)。好比:一张800x480的图片原来占用内存大约是1.46M,增长3倍后图片是3200x1920,占用内存大约是23M。而通常Android系统分配给每一个进程的内存也才一百多M,在低配手机中很容易就产生OOM。学习

如何处理

针对上面的状况,如何处理资源文件呢?由于Android拿到低密度的图片时,在高密度设备会将其放大。因此在添加资源文件时,应该优先使用高品质图片从高密度的目录往下放。优化

Bitmap图片的处理

Bitmap类型的图片也是在开发中常常用到的。对于Bitmap图片若是不加处理直接使用的话,也很容易致使OOM。由于会有一些占用很大的图片被加载到内存中,而真正的需求可能并不须要这么大的图片。spa

接下来的内容大多来自于Google推荐的一种处理Bitmap图片的方法。连接在下面,感兴趣的同窗也能够直接阅读文档。code

developer.android.com/topic/perfo…

在Google的方案中,主要的思想是按需加载Bitmap。所谓的按需加载,就是根据图片的尺寸和要加载图片的ImageView的尺寸对Bitmap进行压缩处理。

获取Bitmap图片的尺寸

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;
复制代码

上面的代码会获取到Bitmap图片的宽、高、MimeType。同时这里有个参数是比较重要的,inJustDecodeBounds这个参数设为true的时候不会在内存中分配Bitmap的空间,只是获取到了Bitmap图片的宽高等信息。

计算压缩比例

public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        //若是Bitmap图片宽高大于ImageView宽高,就缩放图片
        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        //计算缩放比例
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}
复制代码

上面的代码经过图片的尺寸计算Bitmap图片的缩放比例。最终获得的结果inSampleSize就是须要缩放的比例。

得到图片

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}
复制代码

这一步是获取获得最终的Bitmap图片,能够看到BitmapFactory.Options options的inSampleSize是缩放比例,在获取图片以前,将inJustDecodeBounds设置为false,而后再次调用decode方法就得到了最终的Bitma对象。

使用图片加载框架

在处理图片时,特别是网络图片若是咱们想要高效的利用图片资源。这个时候使用图片加载框架是一个很好的选择。好比:Glide框架。这也是Google推荐的图片加载框架。

图片加载框架不只能帮助咱们处理图片。同时还能经过缓存复用图片,提升图片的利用率。

总结

在Android开发中,图片的处理几乎是因此应用都要面对的场景,可以了解一些图片的优化的小技巧,可以提升咱们在开发中的效率与质量。若是各位同窗有更好的方法,欢迎在评论区讨论,你们共同窗习。

相关文章
相关标签/搜索