美文网首页
Bitmap高效加载

Bitmap高效加载

作者: 哎哟小邹 | 来源:发表于2017-12-06 22:49 被阅读0次

    Android对单个应用的内存分配是有限制的,比如16M,这样就导致在加载Bitmap时很容易就导致OOM(out of menory 内存溢出)。

    内存溢出(out of memory)通俗理解就是内存不够,就是所需要的内存达到或超出系统为应用分配的大小。

    为了解决Bitmap对内存造成的困扰,我们需要比较高效的加载Bitmap的策略。


    对于Bitmap高效加载,我们先谈谈Bitmap的加载

    Bitmap在Android中指的是一张图片。加载一张图片我们使用的是Android中 BitmapFactory 类中的方法。BitmapFactory中提供了四类方法:decodeFile,decodeResoure,decodeStream,decodeByteArry。分别可以从文件系统,资源,输入流,及字节数组中加载一个Bitmap对象。其中decodeFile,decodeResoure又间接调用decodeStream方法。这四类方法最终是在Android的底层实现的,对应着BitmapFactory类的几个native方法。


    再来谈谈高效加载图片,核心思想就是改变Bitmap的采样率--inSampleSize。因为我们很多时候显示的图片并不需要加载图片的原始尺寸,我们只需要将图片按一定比例缩小后显示即可。这样在一定程度上降低加载图片的内存,减少了OOM的风险。

    高效加载Bitmap的一般步骤如下:

    1.将BitmapFactory.options的inJustDecodeBonds参数设置为true。

    2.从BitmapFactory.options中取出图片的原始宽高信息。

    3.根据目标View的大小结合原始宽高信息得出相对应的采样率,并设置还给BitmapFactory.options的inSampleSize。

    4.将BitmapFactory.options的inJustDecodeBonds参数设置为true。并重新加载图片。

    inJustDecodeBonds参数,设置为true时, BitmapFactory只会加载 图片的原始宽高信息,并不会真正加载图片,所以这个操作是轻量级的。

    注意:BitmapFactory获取的图片宽高信息和图片的位置以及程序运行的设备有关,比如同一张图片放在不同的drawable目录下或者程序运行在不同屏幕密度的设备上,都可能导致BitmapFactory获取到不同的结果,和Android的资源加载机制有关。

    inSampleSize,即采样率,通过对 inSampleSize的设置,对图片的像素的高和宽进行缩放。

    当inSampleSize=1,即采样后的图片大小为图片的原始大小。小于1,也按照1来计算。 当inSampleSize>1,即采样后的图片将会缩小,缩放比例为1/(inSampleSize的二次方)。inSampleSize的取值应该总是2的指数,如1,2,4,8等。如果外界传入的inSampleSize的值不为2的指数,那么系统会向下取整并选择一个最接近2的指数来代替。比如3,系统会选择2来代替(开发建议)。

    注意:通常需要根据图片宽高实际的大小/需要的宽高大小,分别计算出宽和高的缩放比。但应该取其中最小的缩放比,避免缩放图片太小,到达指定控件中不能铺满,需要拉伸从而导致模糊。

    下面是对上面四个步骤的实现:

    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight){
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            //加载图片
            BitmapFactory.decodeResource(res,resId,options);
            //计算缩放比
            options.inSampleSize = calculateInSampleSize(options,reqHeight,reqWidth);
            //重新加载图片
            options.inJustDecodeBounds =false;
            return BitmapFactory.decodeResource(res,resId,options);
        }
    
        private static int calculateInSampleSize(BitmapFactory.Options options, int reqHeight, int reqWidth) {
            int height = options.outHeight;
            int width = options.outWidth;
            int inSampleSize = 1;
            if(height>reqHeight||width>reqWidth){
                int halfHeight = height/2;
                int halfWidth = width/2;
                //计算缩放比,是2的指数
                while((halfHeight/inSampleSize)>=reqHeight&&(halfWidth/inSampleSize)>=reqWidth){
                    inSampleSize*=2;
                }
            }
    
    
            return inSampleSize;
    

    到这里就可以方便的加载缩放后的图片了:

    mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(),R.mipmap.bitmap,100,100);
    

    相关文章

      网友评论

          本文标题:Bitmap高效加载

          本文链接:https://www.haomeiwen.com/subject/nbhrixtx.html