照片缩略图管理机制、方案和相关文档

1. Android加载Bitmap的策略和相关资料
1.1 加载图片:一般手机相机拍摄的照片分辨率较高,大小在2M左右,加载时需要一定的时间并占用内存,所以不能直接去加载原图,参考1.3中第一篇博文,主要思路是:
1.1.1 获取图片的像素宽高(不加载图片至内存中,所以不会占用资源),关键代码:options.inJustDecodeBounds = true;
1.1.2 计算需要压缩的比例:
private int computeScale(BitmapFactory.Options options, int viewWidth, int viewHeight)
1.1.3 按将图片用计算出的比例压缩,并加载至内存中使用:
bitmap = BitmapFactory.decodeFileDescriptor(fs.getFD(), null, options);
//这里使用decodeFileDescriptor是因为据说decodeFile和decodeSource方法最后会调用Bitmap.createBitmap方法,这个方法使用Java堆区的空间,容易造成内存耗尽,而decodeFileDescriptor使用c区堆(可惜效果不明显,参考资料里的第三篇博文)。
1.2 加载多张图片,参考1.3第二篇博文,主要思路:
1.2.1 建立一个图片缓存池,用于存放图片对应的bitmap对象
1.2.2 在显示的时候,比如listview对应适配器的getView方法里进行加载图片的工作, 先从缓存池通过url的key值取,如果取到图片了直接显示,如果获取不到再建立异步线程去下载图片(下载好后同时保存至图片缓存池并显示),当然我们这里暂时只是加载本地图片。
1.2.3 图片缓存池!这是重点,图片最终要存放在内存中,采用了android.support.v4.util.LruCache,最近最久未使用的图片缓存策略,符合多张图片顺序浏览的行为,设置好这个容器的总容量后,它可以有效管理内存空间。
1.3 在pbAndorid里:
com.jihox.pbandroid.util.NativeImageLoader,提供一个单例的图片加载器,包括各种不同的加载方式,比如加载原始图片,加载自定义大小裁剪的图片,将加载到内存的图片放入LruCache等。
异步加载,使用Handler消息通知和线程池(ThreadPoolExecutor)来实现。这里有一个自定义的容器DynamicBlockingQueue FIFO来维护线程池的就绪任务,该容器为了提高大量加载图片的体验,当用户快速滑动照片列表时,线程池只会去加载他滚动到的那一屏图片,而不是加载从开始到滑动位置的所有图片。
为了提高性能,所有加载的bitmap都采用RGB_565(16位,代替默认的ARGB_8888,32位)。
1.4 相关资料:
Android Bitmap 全面解析(一) 加载大尺寸图片
Android Bitmap 全面解析(二)加载多张图片的缓存处理
Android转换位图BUG,知其然不知其所以然(同学写的文章,只解决了他应用中的问题)
2. Android获取本地图片
前面讲述了图片的加载策略和一些小细节,但从哪儿里加载图片呢?首先,默认只加载SD Card里的图片,使用ContentProvider从MediaStore.Images.Media.EXTERNAL_CONTENT_URI地址获取所有图片的信息列表,可以获取到图片(images 视图)如下信息:

_id为唯一id,_data即文件名称(但他不是unique的),bucket_dispaly_name即相册名,但相册名可能会重复,所以可以用bucket_id来区分,这里我之前也没注意到这个字段。Orientation即图片的旋转角度。
这样就可以获得所有图片的列表,使用Map<相册,相册图片列表>来存储。
3. 为什么使用缩略图?
前面两段为我们加载手机本地图片准备好了条件,并可以正常显示出了图片。但却有个问题:图片显示前需要从2M左右缩小到几百K甚至几十K放入内存,这个压缩的计算量导致应用卡顿、翻页刷新明显,而且在Lru里可能会重复不断的释放。另外,在生成翻页预览时,如果可以提前把每一页制作成缩略图,翻页时直接去加载,而不是每次翻页都根据模板去制作页面,要来的更流畅。所以能避免这个压缩的计算是极好的。
这是,我们注意到android提供一个thumbnails表:

即android会提供图片隐藏的缩略图,于是满心欢喜的使用thumbnails,效果很好,但换了一部手机,却发现thumbnails表虽然有数据但系统却并没有真正生成缩略图,而且对于即时得到的图片不能立即生成缩略图。
所以,就有了自己制作缩略图的想法。
参考博文:
[Android]缩略图Thumbnails
4. 缩略图的生成和管理
4.1 缩略图生成和管理时机:
在主动查询照片和照片变动时进行。
4.2 缩略图生成位置:
sdcard/jihox/pbandroid/.thumbnails,“.”号开头的文件作为隐藏文件,Content provider的file表是不会收录该类文件,我们的程序自然也不会获得该类图片,所有的缩略图都以这种隐藏的方式创建。
4.3 缩略图管理策略
4.3.1 使用SQLite建立数据库《pbandroid.db》
4.3.2 建立thumbnails表,该表记录了我们自己生成的缩略图信息,所有的缩略图都对应一条记录,建表SQL:

CREATE TABLE IF NOT EXISTS thumbnails (_data TEXT PRIMARY KEY, date_modified INTEGER,bucket_display_name TEXT,orientation INTEGER)

_data作为主键,对应images视图里的_data,即图片完整路径名(e.g. sdcard/dcim/sdf.jpeg)。也相当于对应images视图记录的外键。images里_data并不是unique,在有些机子上,同一个_data会出现两条除主键外完全一样的数据,暂时在程序里去重;
date_modified 与images视图里的date_modified对应,比较该字段可以判断文件是否有已修改、需要重新生成缩略图;
bucket_display_name 图片父目录名;
orientation为旋转度,这个需要比较,因为有时候旋转了图片,改变了orientation却并没有影响date_modified。
4.3.3 缩略图生成(thumbails表更新)策略:
4.3.3.1 从images视图里获取allOriginalAIF链表(目前手机里所有的图片)。从thumbnails表里获取allThumbnails链表。
4.3.3.2 第一次两重循环,找到allThumbnails里与allOriginalAIF里不同的数据,即需要更新的条目,顺便可以找到allThumbnails里存在而allOriginalAIF里不存在的数据,即需要删除的条目。
4.3.3.3 第二次两重循环,找到allOriginalAIF里存在而allThumbnails里不存在的数据,即需要新增的条目。
4.3.3.4 将前两步获得三种数据(listToBeAdded,listToBeUpdated,listToBeRemoved)同步更新到thumbnails表里,并对应新增、更新、删除缩略图。
代码见:BaseActivity.java 下的checkImageUpdates(List<AndroidImageFile> allOriginalAIF)方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值