3.3 其他Android组件

Android应用还有一些其他组件,具体包括:Service(服务)、Content Provider(内容提供者)和Broadcast Receiver(广播接收器)。类Service负责为后台功能提供支持,类ContentProvider是多个应用使用数据存储的访问方式,Broadcast Receiver支持多方接收应用所广播的意图信息。
你可能会发现,和组件相比,应用本身是一个相对不重要的单元。设计良好的应用会和Android环境“融为一体”,这些应用可以启动其他应用的活动,使用它们的功能,通过Android支持组件来提供或增强自身的功能。可以把Android的内容提供者和意图理解成辅助性API,应该学会使用它们,以便能够充分利用Android强大的特性并实现和Android平台的无缝集成。

3.3.1 Service

Android的Service类负责为后台执行的任务提供支持,这些任务可能在运行,但是在屏幕上看不到。播放音乐的应用有可能实现成服务,以便在用户查看网页时也能够播放音乐。通过Service,应用可以通过长连接来共享一些功能。这种方式在类似FTP和HTTP这样的Internet服务中是无处不在的,这些服务会一直等待直到客户端的请求触发它们。Android平台不会回收服务的资源,所以一旦某个服务启动了,就很可能可以随时访问该服务,除非内存耗尽了。
和Activity类似, Service类提供了控制其生命周期的方法,如停止和重新启动该服务。

3.3.2 内容提供者

内容提供者组件和RESTful Web服务非常类似,这些组件也是使用URL,而且内容提供者子类的操作和RESTful Web操作也很相似,例如发布和获取数据。在内容提供者组件中的URI通常是以标识符content://开头,本地设备可以识别该标识符,使我们能够访问内容提供者数据。要使用类内容提供者,需要指定一个URI及将如何操作引用的数据。以下是内容提供者支持的操作列表,它提供了大家熟悉的四种基本的数据操作:创建(插入)、读取(查询)、更新和删除。

Insert(插入)

类ContentProvider提供的insert方法和REST POST操作类似,作用就是在数据库中插入新的记录。

Query(查询)

类ContentProvider提供的query方法和REST GET操作类似,它返回一组记录,这些记录保存在一个特殊的集合类Cursor中。

Update(更新)

类ContentProvider提供的update方法和REST UPDATE操作类似,它用新的记录更新数据库中的老记录。

Delete(删除)

类ContentProvider提供的delete方法和REST DELETE操作类似,它删除数据库中与之匹配的记录。

注意: REST是“表现层状态转换”(Representational State Transfer)的简称。它没有HTTP协议那么正式,它更多的是一种使用HTTP作为简单的访问基础的概念框架。虽然REST的实现可能有区别,但它们都力争简单。Android的内容提供者API把类似于REST的操作作为API正式提供,其设计就是遵循REST的简单性原则。可以在Wikipedia上得到更多关于REST的信息。

内容提供者组件是Android内容模型的核心:通过ContentProvider类,应用可以和其他应用共享数据,并管理应用的数据模型。和ContentProvider类密切相关的类ContentResolver,这个类帮助Android系统中的其他组件找到内容提供者。你会发现整个平台有很多内容提供者,它们可以同时用于操作系统和普通应用。值得一提的是,Android应用的核心正是利用内容提供者为新的Android应用提供快速、复杂的功能,包括提供浏览器(Browser)、日历(Calendar)、联系方式(Contacts)、呼叫日志(Call Log)、多媒体(Media)和设置(Settings)等。

内容提供者在进程间通信(InterProcess Communication ,IPC)中是独有的。其不同于在其他平台上构建的一些方式,如CORBA、RMI和DCOM,这些平台重点在于远程过程调用。内容提供者身兼两职,既是持久性机制,同时还负责进程间的通信。除了支持进程间的方法调用外,内容提供者还使得开发人员可以在不同的进程之间高效地共享整个SQL数据库。除了对象分享,内容提供者还管理着所有的SQL表。

内容提供者的使用

考虑到内容提供者在Android中的重要性,这里编写了一个使用内容提供者的简单客户端来介绍它。在这个例子中,使用了最重要的内容提供者之一——Contact数据库,其应该有助于你去了解在应用开发中使用内容提供者的基本方式。类ContentProvider提供了核心的内容提供者API,可以以此为基础创建一些子类来管理特定类型的数据。Activity使用类ContentResolver及其关联的URL来访问特定的内容提供者实例,如下所示:

android其他设备 安卓手机的其他_测试

要使用内容提供者,需要调用按照REST风格定义URI的数据操作,这些操作是在类UriMatcher中定义的。类UriMatcher提供了基于REST的URL的简单字符串匹配工具,它支持字符串通配符。内容提供者的URL的形式往往如下所示:

content://authority/path/id

其中,authority是Java包内容提供者命名空间(通常就是内容提供者的Java命名空间)。以下是一些内容提供者URI示例:

// references a person
content://contacts/people/25
// this URI designates the phone numbers of the person whose ID is "25"
content://contacts/people/25/phones

当开发人员调用内容提供者的query方法时,会返回一个Cursor对象,它实现了android.database.Cursor接口对象。通过该接口,可以使用索引每次检索一条结果(类似于数据库中的一条记录),在检索每一条结果时,索引会自动更新。熟悉JDBC的开发人员可以把android.database.Cursor理解成java.sql.ResultSet。在绝大多数情况下,Cursor对象表示的是在SQLite表上的查询结果。开发人员可以使用底层SQLite表来访问cursor的各个字段。下面这个例子的功能就是遍历Android cursor得到所有字段:

android其他设备 安卓手机的其他_内容提供者_02

注意,无论客户端什么时候使用provider提供的cursor,当客户端操作完成后,关闭cursor是至关重要的。如果没有关闭cursor,会导致严重的内存泄露,从而导致应用崩溃。Android提供两种方式确保在不使用provider cursor时关闭它:
Activity直接调用Cursor.close方法。
Activity调用managedQuery方法查询内容提供者,或调用startManagingCursor(Cursor c)方法。这两种调用都依赖于系统来检查cursor的引用,判断给定的引用是否已经没有活跃的客户端。当引用计数显示所有的客户端已经结束操作时,系统本身会调用Cursor.close方法。
我们将在第12章和第13章更详细地介绍数据和内容提供者。
内容提供者和互联网
内容提供者和Android应用中的Activity组件一起构成了“模型-视图-控制器”(Model-View-Controller,MVC)架构的必要组成部分。除了支持REST风格的操作外,它们还支持MVC的观察者模式(observer pattern)。类ContentResolver提供notifyChange方法,向使用registerContentObserver方法注册了content observer的Cursor对象广播数据库中的变化。
也许你会想:“好吧,但是我所感兴趣的数据是在互联网上。”Android提供了很多可以访问这些数据的工具。你很可能已经使用过某些应用,它们直接使用了Android的网络类来访问互联网上的数据。遗憾的是,你往往可以识别出这些应用,因为它们需要很长时间来访问和检索数据,甚至会在你等待过程中显示进度标示。
如果能够增强内容提供者的功能,使它能够在本地缓存数据,此外,Android以数据库为中心的MVC架构本身也支持在有新数据到达时再在用户屏幕上显示,这样岂不是更好?第13章将会介绍这种方式。第13章将介绍在Android中如何结合用户接口、内容提供者及其相关的类、Android的网络API及MVC支持来创建REST客户端,该客户端会利用内容提供者架构和REST的相似性,使得在应用获取数据的过程中,不需要用户一直盯着进度条。

3.3.3 BroadcastReceiver

BroadcastReceiver(广播接收器)类通过Intent对象实现了另一种Android高层进程间的通信机制。BroadcastReceiver的生命周期比已经介绍过的其他组件的生命周期更简单。和Activity类似,broadcast receiver也是接收Intent对象的处理,不同的是它有自己的用户界面。broadcast receiver的典型使用方式是接收警告,在特定时间激活应用。系统可以把一个intent实例广播给多个接收器。