1.4 Android应用程序组件
Android应用程序与我们以前学习的C语言程序具有明显的不同,主要体现在Android应用程序没有提供像main函数那样的单独程序入口。Android的各个应用之间是相互独立的,且各自运行在各自的进程中。在Android系统中由不同的组件来管理应用程序,按照功能的不同可以分为Activity、Service、ContentProvider和BroadcastReceiver四类组件。组件与组件之间通过Intent来完成通信,应用程序通过View来向用户展示可视化的界面。下面我们分别介绍各个组件。
1.4.1 Activity活动程序
Activity活动程序是Android系统中最常用,也是最基本的工作组件。直观上来说,Activity活动程序相当于用户看到的手机界面。用户程序的每一个界面就是一个Activity,用户通过Activity来与应用程序进行交互。Activity通过视图View显示给用户,视图View将用户的操作信息反馈给Activity来执行,如图1.2所示。
图1.2 Activity活动程序
一个Android应用程序可以包含一个或多个Activity,每个Activity都是独立的。一般来说,Android程序在运行时会将其中一个Activity定为第一个显示的Activity。在程序运行过程中,Activity之间的跳转是通过Intent激活组件来完成的。Intent激活组件负责完成Activity之间的切换和数据传递。
Activity活动程序在Android系统中具有不同的状态,这些状态构成了Activity的生命周期。Activity的生命周期是一个非常重要的内容,将在后面的章节介绍。
1.4.2 Service服务程序
Service服务程序没有像Activity那样的可视化的界面,其是在后台运行的,往往具有较长的生命周期。Service有自己的生命周期,一个Service往往由Activity来启动,当Activity的生命周期结束时,Service仍会继续运行,直到自己的生命周期结束为止。
Service服务程序是Android实现多任务处理的重要组件。例如,Android系统中的音乐播放器便是一个很典型的Service服务程序。用户通过音乐播放器程序的Activity界面来选择歌曲进行播放,此时将启动一个Service来在后台运行播放功能。此时,用户在欣赏音乐的时候,可以转向其他的应用程序来执行别的任务。
同Activity一样,Service服务程序运行于一个应用程序进程的主线程内,所以不会干扰其他组件或用户界面。通常,Service服务程序会派生一个新线程来处理一些较耗时的程序,如下载、大规模计算等。用户的应用程序可以通过一个接口来控制Service服务程序。例如,对于音乐播放器来说,通过接口可以控制音乐播放的暂停、回退、停止等状态。
Service服务程序有两种启动方式:StartService启动服务程序和BindService绑定服务程序。
当用StartService方式启动时,会调用onCreate和onStart来开启,当用StopService方式中止时,调用onDestroy来中止;或者Service服务程序自身调用stopSelf或StopService来中止。
当用BindService方式启动时,会调用onCreate和onBind来开启;当用unbindService方式中止时,调用onDestroy或者onUnbind来中止。
1.4.3 BroadcastReceiver广播接收器
BroadcastReceiver广播接收器负责接收Android系统中的广播通知信息,并作出相应的处理。当Android操作系统或某个应用程序发送广播时,另外的应用程序可以使用BroadcastReceiver广播接收器来接收这个广播,并作出相应的处理。从这里可以看出,广播可以源自于Android系统,也可以来自于应用程序。
源自于Android系统的广播包括时区改变、电池电量低、更改语言选项等。来自应用程序的广播则可以是指定的功能状态,例如数据下载完成后的通知。Android应用程序可以拥有任意数量的广播接收器。所有的接收器均继承自BroadcastReceiver基类。
广播接收器没有像Activity那样的可视化用户界面,但可以采用很多种方式来吸引用户的注意,例如闪烁指示灯、震动、播放声音等。
BroadcastReceiver广播接收器需要注册和注销。Android提供了两种方式来注册广播接收器,一种是在Android Manifest.xml中定义,另一种是直接在程序代码中动态设置。注册好的广播接收器并不一直在后台运行,只有相应的Intent才可以调用。
在使用时,应用程序首先将需要广播的信息封装到Intent中,然后将Intent广播出去。另一个应用程序则通过IntentFilter对象来过滤所有的Intent。最后,BroadcastReceiver广播接收器用一个onReceive()的回调方式来处理接收到的通知。
1.4.4 ContentProvider内容提供器
ContentProvider内容提供器负责实现Android应用程序之间的数据共享。在Android的系统中,应用程序之间是相互独立的,各个应用程序组件运行在不同的进程当中,应用程序所建立的数据只允许自己使用,数据是无法共享的。为了解决这个问题,Android采用ContentProvider内容提供器来实现不同组件间的数据共享。
在Android中,数据可以以文件的形式存储于文件系统,也可以是SQLite数据库或其他方式。ContentProvider内容提供器用来存放和获取数据并使这些数据可以被所有的应用程序访问。这是应用程序之间共享数据的唯一方法。Android系统在android.provider软件包中提供了多种常见的ContentProvider内容提供器,例如音频、视频、照片、联系人和信息等。用户的应用程序要访问这些数据,必须首先获取相应的权限。
在Android中可以采用两种方法进行数据共享:一种是创建一个新的ContentProvider内容提供器子类;另一种是向现有的内容提供器添加数据,此时则要求该内容提供器控制同种类型的数据,且访问者拥有写操作的权限。
在Android系统中,ContentProvider往往将共享的数据定义一个URI,其他应用程序通过Context获得ContentResolver,并传入数据的URI。通过ContentResolver可以与任何一个内容提供器进行通信,来实现对共享数据的管理。使用ContentProvider共享数据时,要重点理解数据模型和URI。
数据模型:ContentProvider为待共享数据创建的一个数据表,每一行代表一条记录,每一列代表某个数据,在数据记录中使用“_ID”标识每条数据。
URI:ContentProvider对外提供的数据集标识。如果存在多个数据集,则需要为每个数据集分配一个独立的URI,每个URI均以“content://”开头。
注意:当应用程序使用ContentProvider访问共享的数据时,必须为该应用程序添加适当的权限。
1.4.5 Intent激活组件
Intent激活组件负责连接两个不同的组件,这是一种运行时的绑定机制。前面介绍过,多个Activity是通过Intent来进行跳转的,Intent在Android操作系统中具有很重要的地位。
在前面介绍的4个基本组件Activity、Service、BroadcastReceiver和ContentProvider中,只有ContentProvider是在ContentResolver发出的请求后被激活,而其他几个组件都是通过Intent来连接的。对于不同类型的组件,Android提供了不同的Intent处理方法。
在Android系统中,除了Intent外,还提供了IntentFilter激活过滤器。IntentFilter相当于Intent的过滤器,即声明该应用程序能接受哪些指定的Intent请求。IntentFilter一般在Android Manifest.xml文件中指定。如果指定了IntentFilter,Android会找到这个组件并激活它;否则,Android就通过比较Intent对象和所有可能对象的IntentFilter,找到对于Intent来说最合适的组件,组件的IntentFilter会告知Android它所能处理的Intent类型。
在Android系统中,应用程序通过Intent向系统发出请求,系统会根据请求查询各组件声明的IntentFilter,找到需要的组件并运行。每当出现一个需要被特定组件处理的请求时,Android会确保那个组件的应用程序进程处于运行状态,或在必要的时候启动它。并确保那个相应组件的实例存在,必要时会创建那个实例。
Intent是由组件名、Action、Data、Category、Extra和Flag六部分组成,其中最重要的是动作action和动作对应的数据data。常见的动作有ACTION_MAIN、ACTION_VIEW、ACTION_CALL、ACTION_EDIT等,一个Intent只能设置一种Action;动作对应的数据是以URI的形式表示的。
IntentFilter是通过检查Action、Data和Category三方面来过滤Intent的。一个IntentFilter可以设置多个Action过滤进行匹配,对数据的URI和数据类型进行匹配。一个IntentFilter还可以设置多个Category过滤进行匹配。
1.4.6 View视图组件
View视图组件负责绘制Activity与用户进行交互的界面。在Android系统中,每个Activity都被给予一个默认的窗口以进行绘制,这都是由Vi e w来实现的。
一般情况下,Activity对应的窗口是铺满整个屏幕的,但也可以采用部分大小屏幕的样式。有时Activity也可能用到多个窗口,例如运行过程中的弹出对话框、提示信息等。
Android的图形界面自下而上可分为三层:底层是Activity,中层是Window;上层是View。View视图组件又可分为两类:View类和ViewGroup类。
View类是所有可视化基本控件类,Android提供了丰富内置的控件视图供用户直接使用,例如按钮、时钟、单选框、复选框、多选框、文本框、菜单、卷轴等。
ViewGroup类是指所有布局控件,即用来控制界面中的基本控件如何布局、摆放。在Android中没有设计布局管理器,而是使用ViewGroup类来控制不同的布局。
应用程序中的可视化界面是由一系列视图构成的,这些视图从Vi e w视图组件继承而来。每个视图均控制着界面中一个特定的矩形空间。父视图包含并组织子视图的布局。位于视图层次最底端的叶节点视图在它们控制的矩形中进行绘制,并对用户的操作作出响应。