第十二章 Bitmap 的加载和 Cache

Bitmap 的高效加载

  1. 由于Bitmap的特殊性以及Android 对单个应用所施加的内存限制,比如16MB,这导致加载 Bitmap 的时候很容易出现内存溢出。
  2. 加载图片:BitmapFactory 类提供了四类方法,decodeFile、decodeResource、decodeStream、decodeByteArray,分别用于支持从文件系统、资源、输入流以及字节数组中加载出一个Bitmap 对象,decodeFile、decodeResource间接调用了decodeStream,这四类方法最终是在Android的底层实现的,对应着BitmapFactory的几个native方法
    3. 如何高效地加载图片?
    采用BitmapFactory.Options来加载所需尺寸的图片,假设通过imageView来显示图片,很多时候ImageView并没有图片的原始尺寸那么大,整张图片加载进来再设置给ImageView显然没必要,通过BitmapFactory.Options就可以按一定的采样率来加载缩小后的图片,将缩小后的图片在ImageView中显示,这样就会降低内存占用从而在一定程度上避免OOM,提高了Bitmap加载时的性能。
  3. 通过 BitmapFactory.Options来缩放图片,主要是用到了inSampleSize参数,即采样率。当 inSampleSize 为1时,采样后的图片和原始图片大小相同;当 inSampleSize 为2时,采样后的图片其宽高均为原图大小的1/2,像素数为原图大小的1/4。
    如何获取采样率?
    (1) 将BitmapFactory.OptionsinJustDecodeBounds参数设为true并加载图片
    (2) 从BitmapFactory.Options中取出原始宽高信息,对应于outWidth、outHeight
    (3) 根据采样率的规则并结合目标view的所需大小计算出采样率inSampleSize
    (4) 将 BitmapFactory.OptionsinJustDecodeBounds设为 false 然后重新加载图片
    inJustDecodeBounds参数 当此参数为 true 时,BitmapFactory只会解析图片的宽高信息,并不会真正地加载图片,该操作是轻量级的。此时BitmapFactory获得的图片宽高信息和图片的位置以及程序运行的设备有关,比如一张图片放在不同的 drawable 目录下,或者程序运行在不同屏幕密度的设备上,都会导致 BitmapFactory 获取到不同的结果,原因是和 Android 的资源加载机制有关。
        BitmapFactory.decodeResource();
        BitmapFactory.decodeFile();
        BitmapFactory.decodeStream();
        BitmapFactory.decodeByteArray();

以上四个方法都是支持采样率加载的,处理方式也是类似的。decodeStream()有些特殊,需要获取流的文件描述符FileDescriptor,通过BitmapFactory.decodeFileDescriptor加载。

Android 中的缓存策略

1. 如何避免过多的流量消耗呢?
缓存。当程序第一次从网上加载图片后,就将其缓存到设备上,为了提高用户体验,往往还会想内存中缓存一份。当应用打算从网络上请求一张图片时,程序会首先从内存中获取,如果内存中没有就从设备中获取,如果设备中没有,就从网络上下载。该缓存策略不仅适用于图片,也适用于其他文件类型。
2. 常用缓存算法:LRU。LRU是近期最少使用算法,核心思想:当缓存满时,会优先淘汰那些近期最少使用的缓存对象。采用LRU算法的缓存有两种:LruCacheDiskLruCache
LruCache
内部采用一个LinkedHashMap以强引用的方式存储外界的缓存对象。当缓存满的时候,LruCache 会移除较早使用的缓存对象,然后再添加对象。LruCache 是线程安全的。
强引用:直接的对象引用
软引用:当一个对象只有软引用存在时,系统内存不足时此对象会被 gc 回收
弱引用:当一个对象只有弱引用存在时,此对象会随时被gc回收
DiskLruCache
磁盘缓存。

ImageLoader 的实现

一个优秀的ImageLoader应该具备如下功能:
图片的同步加载;图片的异步加载;图片压缩;内存缓存;磁盘缓存;网络拉取
图片的同步加载:以同步的方式向调用者提供所加载的图片,该图片可能是从内存、磁盘和网络中拉取的。
图片的异步加载:调用者无需在单独的线程中以同步的方式获取图片,此时ImageLoader需要自己在线程中加载图片并将图片设置给所需的ImageView
图片压缩:降低OOM概率的有效手段
内存缓存、磁盘缓存:极大提高程序效率,有效降低用户流量。
列表错位:对于ListView、GridView等,由于 itemView 的复用导致的列表错位。

优化列表的卡顿现象

不要在主线程做太多的耗时操作即可提高滑动的流畅度。
1. 不要在getView中执行耗时操作。
2. 控制异步任务的执行频率。
如果用户可以频繁上下滑动,就会一瞬间产生上百个异步任务,这些任务会造成线程池的拥堵并随即带来大量的UI更新操作,造成一定程度的卡顿?
解决:可以考虑在列表滑动的时候停止加载图片,开启硬件加速。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值