【Android性能优化】Android图片加载方案--Bitmap的内存管理和优化方案

转载请注明原文地址:http://blog.csdn.net/mxm691292118/article/details/51028953

我把Android重难点和读书笔记都整理在github上:https://github.com/miomin/AndroidDifficulty

如果你觉得对你有帮助的话,希望可以star/follow一下哟,我会持续保持更新。


写在前面:笔者的上一篇博文有提到过,如果不恰当的使用Bitmap,很容易造成OOM。这篇博文就来谈谈应该如何正确的管理Bitmap的内存,以及优化策略。

参考: Google官方教程 – 《Android Training Ccourse》


一、加载按显示需要的比例缩小的图片

1、先来说说屏幕密度

  • 在Android中,Imageview控件的长宽单位一般设置为dp/dip,而不用px。这样做的原因,是因为dp/dip与屏幕像素密度无关,px与屏幕密度有关。在Android中,规定以160dpi为基准,1dip=1px,如果密度是320dpi,则1dip=2px。(所以,同一个imageview,在不同的设备上所显示的长宽的像素是不同的,我们需要根据像素不同,来按比例压缩大图)

  • 如果把一个大小为1024x1024像素的图片显示到大小为512x512像素的ImageView上吗,就没有必要加载整张原图到Bitmap中。

  • 为了告诉解码器去加载一个缩小比例是多少的图片到内存中,需要在BitmapFactory.Options 中设置 inSampleSize 的值。例如, 一个分辨率为2048x2048的图片,如果设置 inSampleSize 为4,那么会产出一个大约512x512大小的Bitmap。

  • 下面的代码是动态获取一个ImageView的长宽像素:
    注意:返回的是像素值(px),而不是dp/dip

    int reqHeight = iv.getLayoutParams().height;
    int reqWidth = iv.getLayoutParams().width;

2、压缩图片

  • 一般来说,加载本地资源图片才需要压缩,加载网络图片,应该让服务器按需压缩,一方面节省流量,另一方面提高加载流畅度
  • 可以通过下面的代码计算inSampleSize的值,就是需要压缩的倍数:
//reqWidth和reqHeight是需要显示的Imageview的width和height
public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // height和width图片长宽的像素
    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;
}
  • 通过下面的方法可以获得压缩后的Bitmap:
    注意:可以通过设置 inJustDecodeBounds 属性为true可以在解码的时候避免内存的分配,它会返回一个null的Bitmap,但是可以获取到 outWidth, outHeight 与 outMimeType。确定好压缩比例后,再将inJustDecodeBounds设置为false。
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);

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

    // 根据inSampleSize压缩图片
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

二、Bitmap缓存

1、缓存类LruCache介绍

  • 在Android3.0之后,一般使用LruCache来缓存Bitmap,它使用一个强引用的LinkedHashMap保存最近引用的对象,并且在缓存超出设置大小的时候剔除(evict)最少使用到的对象。
  • LinkedHashMap会根据LRU算法来排列对象的顺序,新加入的对象添加到头部,刚被使用过的对象也被移动到头部,所以在链表尾部的对象是最久没有被使用过的,一旦链表满了,有新对象加入,就会删除链表尾部的对象。

2、如何给LruCache设置一个合适的大小?

  • LruCache太大的话,容易造成OOM或者分配给应用的剩余内存不够用,LruCache大小的设置,应该考虑下面的因素:
    • (1)应用允许的最大内存是多少?剩下了多少可用的内存?
    • (2)多少张图片会同时显示在屏幕上?</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值