Android 应用通常由一个或多个基本组件组成,前面我们看到 Android 应用中最常用的组件就是 Activity。事实上 Android 应用还可能包括 Service、BroadcastReceiver、ContentProvider 等组件。我们先让读者对这些组件建立一个大致的认识,后面还会对这些组件做更详细的介绍。
1,Activity 和 View
Activity 是 Android 应用中负责与用户交互的组件——大致上可以把它想象成 Swing 编程中的 JFrame 控件。不过它与 JFrame 的区别在于:JFrame 本身可以设置布局管理器,不断地向 JFrame 中添加组件,但 Activity 只能通过 setContentView(View) 来显示指定组件。
View 组件是所有 UI 控件、容器控件的基类,View 组件就是 Android 应用中用户实实在在看到的部分。但 View 组件需要放到容器组件中,或者使用 Activity 将它显示出来。如果需要通过某个 Activity 把指定 View 显示出来,调用 Activity 的 setContentView() 方法即可。
setContentView() 方法可接受—个 View 对象作为参数,例如如下代码:
// 创建一个线性布局管理器
LinearLayout layout = new LinearLayout(this);
// 设置该 Activity 显示 layout
setContentView(layout);
上面的程序通过代码创建了一个 LinearLayou t对象(它是 ViewGroup 的子类,ViewGroup 又是 View 的子类).接着调用 Activity 的 setContentView(layout) 把这个布局管理器显示出来。
setContentView() 方法也可接受一个布局管理资源的 ID 作为参数,例如如下代码:
// 设置该 Activity 显示 main.xml 文件定义的 View
setContentView(R.layout.main);
从这个角度来看,大致上可以把 Activity 理解成 Swing 中的 JFrame 组件。当然,Activity 可以完成的功能比 JFrame 更多,此处只是简单地类比一下。
实际上 Activity 是 Window 的容器,Activity 包含一个 getWindow() 方法,该方法返回谊 Activity 所包含的窗口。对于 Activity 而言,开发者一般不需要关心 Window 对象。如果应用程序不调用 Activity 的 setContentView() 来设置该窗口显示的内容,那么该程序将显示一个空窗口。
Activity 为 Android 应用提供了可视化用户界面,如果该 Android 应用需要多个用户界面,那么这个 Android 应用将会包含多个Activity,多个 Activity 组成 Activity 栈,当前活动的 Activity 位于栈顶。
Activity 色含了一个 setThemeOnt(int resid) 方法束设置其宙门的风格,例如我们希望窗口不显示 ActionBar、以对话框形式显示窗口,都可通过该方法来实现。
2,Service
Service 与 Activity 的地位是并列的,它也代表一个单独的 Android 组件。Service 与 Activity 的区别在于:Service 通常位于后台运行,它一般不需要与用户变互,因此 Service 组件没有图形用户界面。
与 Activity 组件需要继承 Activity 基类相似,Service 组件需要继承 Service 基类。一个 Service 组件被运行起来之后,它将拥有自己独立的生命周期,Service 组件通常用于为其他
组件提供后台服务或监控其他组件的运行状态。
3,BroadcastReceiver
BroadcastReceiver 是 Android 应用中另一个重要的组件,顾名思义,BroadcastReceiver 代表广播消息接收器。从代码实现角度来看,BroadcastReceiver 非常类似事件编程中的监听器。与普通事件监听器不同的是:普通事件监听器脯听的事件源是程序中的对象:而 BroadcastReceiver 监听的事件源是 Android 应用中的其他组件。
使用 BroadcastReceiver 组件接收广播消息比较简单,开发者只要实现自己的 BroadcastReceiver 子类,并重写 onReceive(Context context, Intent intent) 方法即可。当其他组件通过 sendBroadcast()、sendStickyBroadcast() 或 sendOrderedBroadcast() 方法发送广播消息时,如该 BroadcastReceiver 也对该消息 “感兴趣”(通过 IntentFiIter 配置),BroadcastReceiver 的 onReceive(Context context, Intent intent) 方法将会被触发。
开发者实现了自己的 BroadcastReceiver 之后,通常有两种方式来注册这个系统级的 “事件监听器”。
在 Java 代码中通过 Context.registReceiver() 方法注册 BroadcastReceiver。
在 AndroidManifest.xml 文件中使用< raceiver.../> 元素完成注册。
读者此处只要对 BroadcastReceiver 有个大致的印象即可,本书后面的章节还会详细介绍如何开发、使用 BroadcastReceiver 组件。
4,ContentProvider
对于 Android 应用而言,它们必须相互独立,各自运行在自己的 Dalvik 虚拟机实例中,如果这些 Android 应用之间需要实现实时的数据变换。例如我们开发了个发送短信的程序,当发送短信时需要从联系人管理应用中读取指定联系人的数据——这就需要多个应用程序之间进行数据交换。
Android 系统为这种跨应用的数据变换提供了个标准:ContentProvider。当用户实现自己的 ContentProvider 时,需要实现如下抽象方法。
insert(Uri, ContentValues):向 ContentProvider 插入数据。
delete(Uri, ContentValues):删除 ContentProvider 中指定数据。
update(Uri, ContentValues, String, String[]):更新 ContentProvider 中指定数据。
query(Uri,String[], String, String[], String):从 ContentProvider 查询数据。
通常与 ContentProvider 结合使用的是 ContentResolver,一个应用程序使用 ContentProvider 暴露自己的数据,而另一个应用程序则通过 ContentResolver 来访问数据。
5,Intent 和 IntentFilter
严格地说,Intent 并不是 Android 应用的组件,但它对于 Android 应用的作用非常大——它是 Android 应用内不同组件之间通信的载体。当 Android 运行时需要连接不同的组件时,通常就需要借助于 Intent 来实现。Intent 可以启动应用中另一个 Activity,也可以启动一个 Service 组件,还可以发送一条广播消息来触发系统中的 BroadcastReceiver。也就是说, Activity、Service、BroadcastReceiver 三种组件之间的通信都以 Intent 作为载体,只是不同组件使用 Intent 的机制略有区别而己。
当需耍启动一个 Activity 时,可调用 Context 的 startActivity(Intent intent) 或 startActivityForResult(Intent intent, int requestCode) 方法,这两个方法中的 Intent 参数封装了需要启动的目标 Activity 的信息。
当需要启动一个 Service 时,可调用Context 的startService(Intent intent) 方法或 bindService(Intent service, ServiceConnection conn, int ftags) 方法,这两个方法中
更多资源请访问稀酷客(www.ckook.com)的intent参数封装了需要启动的目标Service的信息。
当需要触发一个 BroadcastReceiver 时,可调用 Context 的sendBroadcast(lntent intent)、sandStickyBroadcast(Intent intent) 或 sendOrderedBroadcast(Intent intent, String receiverPermission) 方法来发送广播消息,这三个方法中的 Intent 参数封装了需要触发的目标 BroadcastReceiver 的信息。
通过上面的介绍不难看出.Intent 封装了当前组件需要启动或触发的目标组件的信息,因此有些书上把 Intent 翻译为 “意图”。实际上 Intent 对象里封装了大量关于目标组件的信息,我们后面还会更详细地介绍 Intent 所封装的数据,此处不再深入讲解。
当一个组件通过 Intent 表示了启动或触发另一个组件的 “意图” 之后,这个意图可分为两类。
显式 Intent:显式 Intent 明确指定需要启动或者触发的组件的类名。
隐式 Intent:隐式 Intent 只足指定需要启动或者触发的组件应满足怎样的条件。
对于隐式 Intent 而言,Android 系统无须对该 Intent 做任何解析,系统直接找到指定的目标组件,启动或触发它即可。
对于隐式 Intent 而言,Android 系统需要对该 Intent 进行解析,解析出它的条件,然后再去系统中查找与之匹配的目标组件。如果找到符合条件的组件,就启动或触发它们。
那么 Android 系统如何判断被调用组件是否符合隐式 Intent 呢?这就需要靠 IntentFilter 来实现了,被调用组件可通过 IntentFilter 来声明自己所满足的条件——也就是声明自己到底能处理哪些隐式 Intent。关于 Intent 和 IntentFilter 本书后面还会有进一步阐述,此处不再深入讲解。