本文不涉及UI方面的内容, 如果您是希望了解UI方面的访客, 请跳过此文.

本文将要详细介绍如何实现流畅加载本地图库. 像平时用得比较多应用, 如微信(见下图), 微博等应用, 都实现了图库功能, 其中主要功能包括:

  • 默认显示所有图片
  • 按目录显示图片

另外, 界面要素包括:

  • 图片缩略图
  • 图片目录列表以及目录中包含的图片数

讨论: 在Android上, 如何实现流畅加载本地照片的相册?

知识要点

  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开发案例 - 图库的更多相关文章

  1. AllJoyn+Android开发案例-android跨设备调用方法

    AllJoyn+Android开发案例-android跨设备调用方法 项目须要涉及AllJoyn开源物联网框架.前面主要了解了一些AllJoyn主要的概念.像总线,总线附件,总线对象,总线接口这种概念 ...

  2. Android开发案例 设置背景图片轮播

    点击按钮实现图片轮播效果 实践案例: xml <?xml version="1.0" encoding="utf-8"?> <LinearLa ...

  3. Android开发案例 – 在AbsListView中使用倒计时

    在App中, 有多种多样的倒计时需求, 比如: 在单View上, 使用倒计时, 如(如图-1) 在ListView(或者GridView)的ItemView上, 使用倒计时(如图-2) 图-1 图-2 ...

  4. Android开发案例 - 淘宝商品详情

    所有电商APP的商品详情页面几乎都是和淘宝的一模一样(见下图): 采用上下分页的模式 商品基本参数 & 选购参数在上页展示 商品图文详情等其他信息放在下页展示 知识要点 垂直方向的ViewPa ...

  5. Android开发案例 - 自定义虚拟键盘

    所有包含IM功能的App(如微信, 微博, QQ, 支付宝等)都提供了Emoji表情之类的虚拟键盘,  如下图:    本文只着重介绍如何实现输入法键盘和自定义虚拟键盘的流畅切换, 而不介绍如何实现虚 ...

  6. [Deprecated!] Android开发案例 - 微博正文

    Deprecated! 更好的实现方式: 使用 android.support.design.widget.CoordinatorLayout. 本文详细介绍如何实现如下图中的微博正文页面效果, 其中 ...

  7. Android开发案例 - 欢迎界面

    本文详细描述了如何实现如下图中的微信启动界面. 该类启动界面的特点是在整个Application的生命周期里, 它只会出现在第一次进入应用时, 即便按回退键到桌面之后. 使用该类启动界面的应用还有: ...

  8. Android开发案例 - 淘宝商品详情【转】

    http://erehmi.cnblogs.com/ 所有电商APP的商品详情页面几乎都是和淘宝的一模一样(见下图): 采用上下分页的模式 商品基本参数 & 选购参数在上页展示 商品图文详情等 ...

  9. Android开发案例 点击按钮出现 简易的消息提示框

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

随机推荐

  1. Xamarin中使用DatePickerDialog的相关问题

    在Xamarin中在使用Datepicker的时候,一般情况下只需要在对应的按钮或其他控件的点击事件中使用如下语句即可完成: EditText etBirthday = FindViewById< ...

  2. 分布式唯一ID生成服务

    SNService是一款基于分布式的唯一ID生成服务,主要用于提供大数量业务数据建立唯一ID的需要;服务提供最低10K/s的唯一ID请求处理.如果你部署服务的CPU资源达到4核的情况下那该服务最低可以 ...

  3. Mono 4.0 Mac上运行asp.net mvc 5.2.3

    Mono 4.0 已经发布,二进制包已经准备好,具体的发布说明参见:http://www.mono-project.com/docs/about-mono/releases/4.0.0/. 今天在Ma ...

  4. Building the Testing Pipeline

    This essay is a part of my knowledge sharing session slides which are shared for development and qua ...

  5. ABP源码分析三:ABP Module

    Abp是一种基于模块化设计的思想构建的.开发人员可以将自定义的功能以模块(module)的形式集成到ABP中.具体的功能都可以设计成一个单独的Module.Abp底层框架提供便捷的方法集成每个Modu ...

  6. Memcached和Redis比较

    一.存储 Memcached基本只支持简单的key-value存储方式.Redis除key-value之外,还支持list,set,sorted set,hash等数据结构:Redis支持数据的备份, ...

  7. div中设置滚动条的问题

    <div srtle="width:100px;height:50px;"></div> 这样的一个div,当文本超出的时候我们就会设: overflow: ...

  8. 【原】SDWebImage源码阅读(二)

    [原]SDWebImage源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 解决上一篇遗留的坑 上一篇中对sd_setImageWithURL函数简单分析了一下,还 ...

  9. 【分布式】Zookeeper的Leader选举

    一.前言 前面学习了Zookeeper服务端的相关细节,其中对于集群启动而言,很重要的一部分就是Leader选举,接着就开始深入学习Leader选举. 二.Leader选举 2.1 Leader选举概 ...

  10. 匹夫细说C#:从园友留言到动手实现C#虚函数机制

    前言 上一篇文章匹夫通过CIL代码简析了一下C#函数调用的话题.虽然点击进来的童鞋并不如匹夫预料的那么多,但也还是有一些挺有质量的来自园友的回复.这不,就有一个园友提出了这样一个代码,这段代码如果被编 ...