首页 » Android程序设计:第2版 » Android程序设计:第2版全文在线阅读

《Android程序设计:第2版》其他Android组件

关灯直达底部

Android应用还有一些其他组件,具体包括:Service(服务)、Content Provider(内容提供者)和Broadcast Receiver(广播接收器)。Service类负责为后台功能提供支持,ContentProvider类是多个应用使用数据存储的访问方式,Broadcast Receiver支持多方接收应用所广播的意图信息。

组件中还包括Application类,你可能会发现,和组件相比,应用本身是一个相对不重要的单元。设计良好的应用会和Android环境“融为一体”,这些应用可以启动其他应用的活动,使用它们的功能,通过Android支持组件来提供或增强自身的功能。

意图和Android应用的标准集对应的常数信息可以在:http://developer.android.com/guide/topics/intents/intents-filters.html和http://developer.android.com/guide/appendix/g-app-intents.html中找到。可以把Android的内容提供者和意图理解成辅助性API,应该学会使用它们,以便能够充分利用Android强大的特性并实现和Android平台的无缝集成。

Service

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

和Activity类似,Service类提供了控制其生命周期的方法,如停止和重新启动该服务。

内容提供者

内容提供者(Content Provider)组件和RESTful Web服务非常类似,这些组件也是使用URL,而且ContentProvider子类的操作和RESTful Web操作也很相似,例如发布和获取数据。在内容提供者组件中的URI通常是以标识符content://开头,本地设备可以识别该标识符,使我们能够访问内容提供者数据。要使用类ContentProvider,需要指定一个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的信息:http://en.wikipedia.org/wiki/REST。

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

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

内容提供者的使用

当构建基于服务器的Web应用时,开发人员通常有两种不同的API访问方式。首先是构建程序所必须的代码、库和数据模型。其次,开发人员还可能调用其他Web应用,使用定义好的API获取数据和服务。同样,Android提供也两级API:一是代码直接访问的库和服务,二是通过内容提供者可用的各种服务。考虑到内容提供者在Android中的重要性,这里编写了一个使用内容提供者的简单客户端来介绍它。

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


Cursor c = getContentResolver.query(      android.provider.ContactsContract.Data.CONTENT_URI,      new String {            android.provider.ContactsContract.Data._ID,            android.provider.ContactsContract.Phone.NUMBER},      null,      null,      null);;  

Contacts数据库是在另一个进程中运行的独立应用。要使用内容提供者,需要调用按照REST风格定义URI的数据操作。内容提供者的URL的形式往往如下所示:


content://authority/path/id  

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


// references a personcontent://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得到所有字段:


// code from an activity methodCursor contactsCursor = getContentResolver.query(    ContactsContract.Contacts.CONTENT_URI,    null,    null,    null,    null);if (contactsCursor.moveToFirst) {   int idx = contactsCursor.getColumnIndex(Contacts.People.DISPLAY_NAME);   do { name = contactsCursor.getString(idx); }   while (contactsCursor.moveToNext);}  

注意,无论客户端什么时候使用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的相似性,使得在应用获取数据的过程中,不需要用户一直盯着进度条。

BroadcastReceiver

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