撩一撩B妹(BitMap)

2018-03-08  本文已影响17人  SheepYan9

撩一撩B妹(BitMap)

为什么要撩BitMap?

做android必然会撩到BitMap,撩过BitMap的都知道,BitMap可不是你想撩就能撩,她脾气可是很不好的,是一言不合就OOM.So 学好撩妹姿势是多么的重要

历史演进

言归正传,BitMap会出现OOM其实是有历史原因的:

介于现在已经minSdk至少在14以上了,所以接下来就不讨论手动回收的问题;

BitMap在到底占多大?

至于为什么会乘以4,那就看源码吧:

static const uint8_t gSize[] = {
    0,  // Unknown
    1,  // Alpha_8
    2,  // RGB_565
    2,  // ARGB_4444
    4,  // RGBA_8888
    4,  // BGRA_8888
    1,  // kIndex_8
  };

小结

BitMap 的大小涉及到的因素有:

防止她红杏出墙(OOM)

BitMap内存管理

防止BitMap OOM 就应该先了解系统对BitMap的管理,请移驾到:

将oom 降低到最小发生几率

由于android以及第三方手机厂商平台的差异化,oom永远都会是crash上的常客;

图片加载的问题目前开源社区有了很多优秀的depends,例如:fresco ,picaso, glide 。我个人不建议自己从零开始造轮子写加载库,但是可以去查看他们的源码,学习他的实现方式;

如果很不幸,App中会隔三差五来个OOM 那个不要慌张:

BitmapFactory.Options提供一些附加属性来指定decode的选项,解析Bitmap时用到2个重要参数: 1.inJustDecodeBounds 设置为true后,decode方法解析Bitmap时会返回一个null,只讲这个图片的原始大小(单位是像素)存入BitmapFactory.Options对象的options.outHeight和options.outWidth中,这样可以在不分配内存的情况下得到图片的尺寸信息。 2.inSampleSize 这个参数代表缩小比例,如果是1,代表原始尺寸,如果>1,假设为2,则缩小后图片像素值为原图的1/4(长1/2,宽1/2),同等格式下,占用内存也变为原来的1/4。decoder以2的幂作为系数,接近2的幂的数值都会被处理为最接近的2的幂值,3.4~4,2.1~2,这样。

缩小比例值


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

    if (height > reqHeight || width > reqWidth) {  

        final int halfHeight = height / 2;  
        final int halfWidth = width / 2;  

        while ((halfHeight / inSampleSize) > reqHeight  
                && (halfWidth / inSampleSize) > reqWidth) {  
            inSampleSize *= 2;  
        }  
    }  

    return inSampleSize;  
}   

在调用以上方法前,记得设置options.inJustDecodeBounds = true; 调用后算出比例后,则调用BitmapFactory.decodexxxx(res, resId, options);

举个栗子

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

    final BitmapFactory.Options options = new BitmapFactory.Options();  
    options.inJustDecodeBounds = true;  
    BitmapFactory.decodeResource(res, resId, options);  

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

    options.inJustDecodeBounds = false;  
    return BitmapFactory.decodeResource(res, resId, options);  
}  

就可以mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

int cacheSize = 4 * 1024 * 1024; // 4MiB 一般是可用内存的1/8
LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) {
    protected int sizeOf(String key, Bitmap value) {
        return value.getByteCount();
    }
}

上一篇下一篇

猜你喜欢

热点阅读