2.2 Intent
Intent在Android程序开发中的作用很大,可以使用Intent来启动一个Activity,可以发起一个广播(Broadcast),也可以启动或绑定一个服务(Service)。Intent最常用的方法是用来启动一个Activity,同时也可以携带数据,它还有两个重要的属性:action和data。下面我们将揭开Intent的神秘面纱。
2.2.1 Intent组件的概念
Intent在英语中的本意是“意图”。在Android中,Intent是一类特殊的组件,它负责对应用中一次操作的动作及动作相关的数据进行描述,Android则根据此描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。因此,Intent在Android中承担着一种指令传输的作用,就好比人身体中的神经系统。
Android中提供了Intent组件来实现Activity组件间的交互与通信。不仅是Activity,在后面学到的Service和BroadcastReceiver等都是通过Intent组件关联起来的。Intent不仅可用于应用程序内部,也可用于程序之间的交互。由于Intent的出现,组件仅需将自己需要的功能通过Intent进行描述,而不必具体实现对组件的引用,这些工作全部由底层的Android Runtime来实现,因此Intent最大的优点就是完美地实现了调用者与被调用者之间的解耦。
注:解耦是软件构架中的一个术语。所谓解耦就是降低组件之间的耦合性。耦合指的是组件之间的依赖性,如果一个组件发生变化,与之相关的组件也必须要随之更新以保持它们之间的依赖关系,则称二者是耦合的。在一个系统中,如果组件之间的关系都是耦合的,那么当系统维护时,其中一个组件更新,系统中的其他组件都要随之改变,这显然是一种很糟糕的设计。因此,系统构架师追求的终极目标就是其他组件间的松散耦合。Android在设计之初,吸取了现有系统的优秀设计理念,提出了Intent组件来关联整个Android应用中的组件,这是Android应用的最大特色之一。
既然Intent的地位那么重要,前面说了Intent是描述Android中一次操作的对象,那么Intent中都包含哪些属性信息?
Intent组件包含以下属性。
1.action要执行的动作
SDK中定义了以下一些标准的动作。
ACTION_CALL:入口Activity拨打电话。
ACTION_EDIT:入口Activity供用户编辑信息。
ACTION_MAIN:作为初始Activity启动任务,没有数据输入和输出。
ACTION_SYNC:入口Activity在服务器和移动设备间同步数据。
ACTION_BATTERY_LOW:通知BroadCast Receiver电池电量低。
ACTION_HEADSET_PLUG:通知BroadCast Receiver设备附近被插入或拔下。
ACTION_SCREEN_ON:通知BroadCast Receiver屏幕已打开。
ACTION_TIMEZONE_CHANGED:通知BroadCast Receiver时区设置已经改变。
当然,开发人员也可以自定义动作(自定义动作在使用时,需要加上包名作为前缀,如“com.example.project.SHOW_COLOR”),并可定义相应的组件如Activity来处理自定义动作。
2.data
Android中采用指向数据的一个URI来表示数据,如在联系人应用中,一个指向某联系人的URI可能为:content://contacts /1。对于不同的动作:其URI数据类型是不同的(可以设置type属性指定特定类型数据),如ACTION_EDIT指定Data文件URI,打电话为tel:URI,访问网络为http:URI,而由Content Provider提供的数据则为content:URI。
3.type(数据类型),显式指定Intent的数据类型
一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。
4.category(类别),被执行动作的附加信息
例如,ALTERNATIVE_CATEGORY表示当前的Intent是一系列可选动作中的一个,这些动作可以在同一块数据上执行。其他常用的category还有以下几种。
CATEGORY_BROWSABLE:目标组件可以被浏览器安全调用,用来显示页面中的链接的内容,如图像或电子邮件信息等。
CATEGORY_HOME:目标Activity是设备启动时第一个启动的Activity。
CATEGORY_LAUNCHER:目标Activity应该显示在桌面中。
CATEGORY_PREFERENCE:目标Activity是一个选项模板。
注意:每一个通过startActivity方法发出的隐式Intent都至少有一个category,即“android.intent.category.DEFAULT”,所以,所有希望接收隐式Intent的Activity都应该包括:“android.intent.category.DEFAULT”这一category属性,不然将导致Intent匹配失败。
5.component(组件),指定Intent的目标组件的类名称
通常Android会根据Intent中包含的其他属性的信息,如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果直接指定component属性,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其他所有属性都是可选的。
说明:对于指定了component属性的Intent,因为它明确指定了目标组件的类名称,称为显式Intent;反之,称为隐式Intent。
6.extras(附加信息),包含所有附加信息的集合
使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。
2.2.2 实现Activity页面跳转
在Android当中,Activity的跳转有两种方法,第一个是利用startActivity(Intent intent);的方法,第二个则是利用startActivityForResult(Intent intent, int requestCode);的方法。从字面上来看,这两者之间的差别只在于是否有返回值的区别,实际上也确实只有这两种区别。
1)首先在Java文件下默认的MainActivity添加了监听器setOnClickListener(),实现监听的方法是实现OnClickListener接口,在此方法中建立intent对象。在src中分别创建两个Activity:MainActivity.java和secondActivity.java。
2)编写两个Activity类文件,详细内容请参考项目源码。
【例2-5】
MainActivity.java的主要代码如下。
secondActivity.java的主要代码如下。
3)在resource→layout中分别创建两个Activity对应的布局文件,分别为activity_main.xml和second_activity.xml。
编写两个XML文件,详细内容请参考项目源码。
activity_main.xml的主要代码如下。
second_activity.xml的主要代码如下。
4)最后是<string>文件更改你想要的标题属性。
5)程序运行结果如图2-4和图2-5所示。
图2-4 登录界面
图2-5 登录成功
2.2.3 Intent实现不同页面的传参
一个Android应用程序很少会只有一个Activity对象,如何在多个Activity之间进行跳转?以下是Android中页面跳转以及传值的几种方式。Activity跳转与传参,主要是通过Intent类来连接多个Activity,通过Bundle类来传递数据。Bundle类是一个用于将字符串与某组件对象建立映射关系的组件。Bundle组件与Intent配合使用,可在不同的Activity之间传递数据。Bundle类的常用方法如下。
putString(String key, String value):“键—值对”以字符串的形式存放到Bundle对象中。
remove(String key):移除指定key的值。
getString(String key):获取指定键为key的值。下面是应用Intent在不同的Activity之间传递数据的案例。
【例2-6】
1)该例子在【例2-5】的基础上,实现了传参跳转。在src中分别创建两个Activity:MainActivity.java和secondActivity.java。
2)编写两个Activity类文件,详细内容请参考项目源码。
MainActivity.java和secondActivity.java的主要代码如下。
3)在resource→layout中分别创建两个Activity对应的布局文件,分别为activity_main.xml和second_activity.xml。
跳转到的第二个页面布局文件:second_activity.xml,代码如下。
4)最后更改<string>中的窗口属性。
5)程序运行结果如图2-6和图2-7所示。
图2-6 信息发送页面
图2-7 跳转页面
当然,Intent还可以实现其他组件之间的信息传递,这些内容将在后面的章节中进行介绍。