Android开发案例 - 图库
本文不涉及UI方面的内容, 如果您是希望了解UI方面的访客, 请跳过此文.
本文将要详细介绍如何实现流畅加载本地图库. 像平时用得比较多应用, 如微信(见下图), 微博等应用, 都实现了图库功能, 其中主要功能包括:
- 默认显示所有图片
- 按目录显示图片
另外, 界面要素包括:
- 图片缩略图
- 图片目录列表以及目录中包含的图片数

讨论: 在Android上, 如何实现流畅加载本地照片的相册?
知识要点
- ContentProvider - 数据存取接口
- CursorLoader - Cursor异步加载器
- Android Universal Image Loader
p.s. 实现图库的难点就在于, 如何快速的查询出图片以及目录信息, 貌似 Android 没有直接提供这样的接口, 我们只可以用 android.provider.MediaStore.Images.Media 和 android.provider.MediaStore.Images.Thumbnails. 我们虽然能使用 Thumbnails 查询出缩略图信息和图片ID, 但是它没有提供图片的详细信息, 另外, 如果用于保存缩略图的信息或者目录被(意外或者人为)删除了, 那使用 Thumbnails 基本上就没有什么意义了. 因此, 我们在这里使用 Media 来查询图片以及目录.
实现代码
> 定义
static final Uri CONTENT_URI = Media.EXTERNAL_CONTENT_URI;
static final String SORT_ORDER = Media.DATE_MODIFIED + " DESC";
在这里, 我们只查询sdcard上的图片, 并按照修改时间倒序排列.
> 查询图片
代码略, 直接使用 CursorLoader 按 SORT_ORDER 顺序加载图片, 如果指定了目录, 则设置 Media.BUCKET_ID + "=?" 的查询条件
> 查询目录
和查询图片一样, 也使用CursorLoader来加载数据, 只不过设置的参数不同而已, 如下:
// 方法一
static final String[] PROJECTION_D = {
"DISTINCT " + Media.BUCKET_ID,
Media.BUCKET_DISPLAY_NAME,
"COUNT(*) AS " + Media._COUNT};
// 方法二
static final String[] PROJECTION = {
Media.BUCKET_ID,
Media.BUCKET_DISPLAY_NAME,
Media._ID,
"COUNT(*) AS " + Media._COUNT};
static final String SELECTION = "1=1) GROUP BY (" + Media.BUCKET_ID;
static final String[] SELECTION_ARGS = null;
需要说明的是, 如果对应的目录不需要显示首张图片的缩略图, 那么可以使用方法一, 否则使用方法二(PROJECTION 要与 SELETION 配合使用, 而方法一不需要). 其他参数对应设置到CursorLoader即可.
优化策略
最后, 需要提到的一点就是, 我们使用 UIL(即, Android Universal Image Loader) 加载图片, 但是每次加载都是我们查询出来的原图, 按照github上演示代码的全局初始设定, 加载到三五屏, 第一屏的图片就已经不在内存缓存里, 如果重新滚动到第一屏要显示第一屏图片的话, 就还得从原图读取, 用户体验就很差了. 而我们看到Android相册, 微信相册等应用, 加载很流畅. 通过观察这些应用缓存, 能看到只要浏览很多未被浏览的图片, 那缓存就会变大. 因此, 可以想到的可实现的方式就是:
- 利用UIL缓存原图为较小尺寸的缩略图, 比如320px或者96px
到这里, 按此方法实现的图库的性能以及用户体验基本和Android相册差不多了. 此方法唯一不足的是, 需要应用自己缓存缩略图, 可以假想下, 如果手机上已安装的80%的应用都有这样的一个功能页面, 那岂不是每个应用都要自己生成一套缩略图?
END.
Android开发案例 - 图库的更多相关文章
- AllJoyn+Android开发案例-android跨设备调用方法
AllJoyn+Android开发案例-android跨设备调用方法 项目须要涉及AllJoyn开源物联网框架.前面主要了解了一些AllJoyn主要的概念.像总线,总线附件,总线对象,总线接口这种概念 ...
- Android开发案例 设置背景图片轮播
点击按钮实现图片轮播效果 实践案例: xml <?xml version="1.0" encoding="utf-8"?> <LinearLa ...
- Android开发案例 – 在AbsListView中使用倒计时
在App中, 有多种多样的倒计时需求, 比如: 在单View上, 使用倒计时, 如(如图-1) 在ListView(或者GridView)的ItemView上, 使用倒计时(如图-2) 图-1 图-2 ...
- Android开发案例 - 淘宝商品详情
所有电商APP的商品详情页面几乎都是和淘宝的一模一样(见下图): 采用上下分页的模式 商品基本参数 & 选购参数在上页展示 商品图文详情等其他信息放在下页展示 知识要点 垂直方向的ViewPa ...
- Android开发案例 - 自定义虚拟键盘
所有包含IM功能的App(如微信, 微博, QQ, 支付宝等)都提供了Emoji表情之类的虚拟键盘, 如下图: 本文只着重介绍如何实现输入法键盘和自定义虚拟键盘的流畅切换, 而不介绍如何实现虚 ...
- [Deprecated!] Android开发案例 - 微博正文
Deprecated! 更好的实现方式: 使用 android.support.design.widget.CoordinatorLayout. 本文详细介绍如何实现如下图中的微博正文页面效果, 其中 ...
- Android开发案例 - 欢迎界面
本文详细描述了如何实现如下图中的微信启动界面. 该类启动界面的特点是在整个Application的生命周期里, 它只会出现在第一次进入应用时, 即便按回退键到桌面之后. 使用该类启动界面的应用还有: ...
- Android开发案例 - 淘宝商品详情【转】
http://erehmi.cnblogs.com/ 所有电商APP的商品详情页面几乎都是和淘宝的一模一样(见下图): 采用上下分页的模式 商品基本参数 & 选购参数在上页展示 商品图文详情等 ...
- Android开发案例 点击按钮出现 简易的消息提示框
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
随机推荐
- SVG:linearGradient渐变在直线上失效的问题解决方案
SVG开发里有个较为少见的问题. 对x1=x2或者y1=y2的直线(line以及path),比如: <path d="M200,10 200,100" stroke=&quo ...
- Spring7:基于注解的Spring MVC(下篇)
Model 上一篇文章<Spring6:基于注解的Spring MVC(上篇)>,讲了Spring MVC环境搭建.@RequestMapping以及参数绑定,这是Spring MVC中最 ...
- 【Java并发编程实战】----- AQS(一):简介
在前面博客中,LZ讲到了ReentrantLock.ReentrantReadWriteLock.Semaphore.CountDownLatch,他们都有各自获取锁的方法,同时相对于Java的内置锁 ...
- JQuery插件定义
一:导言 有些WEB开发者,会引用一个JQuery类库,然后在网页上写一写$("#"),$("."),写了几年就对别人说非常熟悉JQuery.我曾经也是这样的人 ...
- 跟我一起数据挖掘(23)——C4.5
C4.5简介 C4.5是一系列用在机器学习和数据挖掘的分类问题中的算法.它的目标是监督学习:给定一个数据集,其中的每一个元组都能用一组属性值来描述,每一个元组属于一个互斥的类别中的某一类.C4.5的目 ...
- ABP(现代ASP.NET样板开发框架)系列之3、ABP分层架构
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之3.ABP分层架构 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...
- 初学者--bootstrap(六)组件中的下拉菜单----在路上(10)
组件---下拉菜单 用于显示链接列表的可切换.有上下文的菜单.下拉菜单的 JavaScript 插件让它具有了交互性. 将下拉菜单触发器和下拉菜单都包裹在 .dropdown 里,或者另一个声明了 p ...
- word-break: break-all;、word-break: keep-all; 、word-wrap: break-word;和white-space:nowrap;都有什么作用
小颖最近心情不好,心情不好就容易做傻事,所以昨天就干了件傻事 小颖昨天脑子一抽去拔罐了,拔完我就~~~~~~~~~~~~疼死宝宝了,昨晚一晚都没睡好,都不敢平躺,难受一晚上,早上到公司后困得啊,也是傻 ...
- android笔记:获取View组件宽度以及ViewTreeObserver
View宽高测量方法: 测量方法有三种,如下: 1)(直接在onCreate()执行) int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureS ...
- Javascript 中 with 的替代方案和String 中的正则方法
这几天在升级自己的MVVM 框架,遇到很多小问题,就在这里统一解决了. with 语法 在代码中,要执行这么一个函数 function computeExpression(exp, scope) { ...