Android大图片处理

图片缓存架构

BitMap创建方式
1.BitMapFactory.decodeResoure()  最消耗资源,因为他会根据手机屏幕进行适配(慎用,比较消耗性能最大的)
//第一步
if (opts == null) {
            opts = new Options();
        }

        if (opts.inDensity == 0 && value != null) {
            final int density = value.density;
            if (density == TypedValue.DENSITY_DEFAULT) {
                opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
            } else if (density != TypedValue.DENSITY_NONE) {
                opts.inDensity = density;
            }
        }
        if (opts.inTargetDensity == 0 && res != null) {
            opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
        }

//第二步
bm = nativeDecodeAsset(asset, outPadding, opts);
2.BitMapFactory.decodeFile()(推荐,是通过调用native方式创建BitMap,消耗性能最少)
//Jni调用
 private static Bitmap decodeStreamInternal(InputStream is, Rect outPadding, Options opts) {
        // ASSERT(is != null);
        byte [] tempStorage = null;
        if (opts != null) tempStorage = opts.inTempStorage;
        if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
        return nativeDecodeStream(is, tempStorage, outPadding, opts);
    }
3.BitMapFactory.decodeByteArray()(推荐,是通过调用native方式创建BitMap,消耗性能最少)
 public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
        if ((offset | length) < 0 || data.length < offset + length) {
            throw new ArrayIndexOutOfBoundsException();
        }

        Bitmap bm;

        Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap");
        try {
            bm = nativeDecodeByteArray(data, offset, length, opts);

            if (bm == null && opts != null && opts.inBitmap != null) {
                throw new IllegalArgumentException("Problem decoding into existing bitmap");
            }
            setDensityFromOptions(bm, opts);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
        }

        return bm;
    }
BitMap创建与优化

1.BitmapFactory.decodeFile()
2.BitmapFactory.Options options= new BitmapFactory.Options();
options.inPreferredConfig配置

这里写图片描述

BitMap大图片的处理

1.
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;

2.如果我们有个图片是1024*768的图片显示在128*60的ImageView是毫无意义的,那么我们应该如何出处理呢?谷歌官方压缩的算法处理如下:

//计算出最优的压缩值
//参数1 :Options对象 参数2:请求的宽(ImageView的宽度) 参数3:请求的高度(ImageView的高度)
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) {
        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;
}

3.真正的使用

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
    //如果自己手动设置压缩比,最好是设置为2的倍数,如果压缩比是2,那么图片压缩成1/4
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

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

Android开发文档地址
https://developer.android.com/training/displaying-bitmaps/load-bitmap.html

BitMap各个版本的实现机制
  • 内存资源回收: Android 2.3(API Level 10)- 由于存储图像数据的Buffer分配在Native内存中, 并且只能通过 recycle( ) 来显式释放Buffer , 而3.0+中,该Buffer则分配在Dalvik Heap中, 因此 recycle( ) 通常当成兼容向下版本的调用. p.s. 该Buffer可在Android源码Bitmap.java中找到.

  • 内存重利用: 3.0+允许开发者将已存在的Bitmap.Buffer分配给新的Bitmap来使用, 不过Bitmap之间的大小要严格相同, 而4.4(API Level 19)+则改变这一状况.

*BitmapFactory.Options: 详见SDK API Reference.

扩展阅读
  • 上述都只是针对单个Bitmap的内存管理, 但是在开发中, 难免会需要管理大量的Bitmap, 那应该怎么办?

  • 在API Level 12中, 可以通过LruCache来缓存大量的内存Bitmap. 除此之外, 在Android源码中, 可以找到, 一个名为DiskLruCache的类, 它可以文件形式缓存Bitmap.

LruCache和DiskLruCache类可以参考
http://blog.csdn.net/hello_word1024/article/details/51638770
中贴出的地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值