Android应用将会根据Intent来启动指定组件,至于到底启动哪个组件,则取决于Intent的各属性。本期将详细介绍Intent的各属性值,以及 Android如何根据不同属性值来启动相应的组件。
Intent 对象大致包含 Component、Action、Category、Data、Type、Extra 和 Flag 这 7 种属性,其中Component用于明确指定需要启动的目标组件,而Extra则用于携带需要交换的数据。
一、Component属性
Intent 的 Component 属性需要接受一个 ComponentName 对象,ComponentName 对象包含如下几个构造器。
· ComponentName(String pkg, String cls):创建pkg所在包下的cls类所对应的组件。
· ComponentName(Context pkg, String cls):创建pkg所对应的包下的cls类所对应的组件。
· ComponentName(Context pkg, Class<?> cls):创建 pkg 所对应的包下的 cls 类所对应的组件。
上面几个构造器的本质是相同的,这说明创建一个ComponentName需要指定包名和类名。这样就可以唯一地确定一个组件类,这样应用程序即可根据给定的组件类去启动特定的组件。
除此之外,Intent还包含了如下三个方法。
· setClass(Context packageContext, Class<?> cls):设置该 Intent 将要启动的组件对应的类。
· setClassName(Context packageContext, String className):设置该 Intent 将要启动的组件对应的类名。
· setClassName(String packageName, String className):设置该 Intent 将要启动的组件对应的类名。
指定Component属性的Intent已经明确了它将要启动哪个组件,因此这种Intent也被称为显式Intent,没有指定Component属性的Intent被称为隐式Intent。
下面的示例程序示范了如何通过显式Intent (指定了 Component属性)来启动另一个 Activity。该程序的界面布局很简单,界面中只有一个按钮,用户单击该按钮将会启动第二个Activity。此处不再给出该程序的界面布局文件。该程序的Java代码如下:
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
上面程序中的onClick回调方法里面的代码用于创建ComponentName对象,并将该对象设置成Intent 对象的Component属性,这样应用程序即可根据该Intent的意图去启动指定组件。 实际上,这几行关键代码完全可以简化为如下形式:
1. // 根据指定组件类来创建Intent
2. Intentintent=newIntent(MainActivity.this,SecondActivity.class);
3. startActivity(intent);
从上面的代码可以看出,当需要为Intent设置Component属性时,实际上Intent己经提供了一个简化的构造器,这样方便程序直接指定启动其他组件。
当程序通过Intent的Component属性(明确指定了启动哪个组件)启动特定组件时,被启动组件几乎不需要使用<intent-filter.../>进行配置。
程序的SecondActivity也很简单,它的界面布局中只包含一个简单的文本框,用于显示该 Activity对应的Intent的Component属性的包名、类名。该Activity的Java代码如下:
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 |
|
运行上面的程序,通过第一个Activity中的按钮进入第二个Activity中,将可以看到下图所示的界面。
二、Action属性
Intent的Action属性的值是一个普通的字符串,代表该Intent所要完成的一个抽象动作。
Action要完成的只是一个抽象动作,这个动作具体由哪个组件(或许是Activity,或许是 BroadcastReceiver)来完成,Action这个字符串本身并不管。比如Android提供的标准Action: Intent.ACTION_VIEW,它只表示一个抽象的查看操作,但具体查看什么、启动哪个Activity 来查看,Intent.ACTION_VIEW并不知道——这取决于Activity的<intent-filter.../>配置,只要某个Activity的<intent-filter.../>配置中包含了该ACTION_VIEW,该Actvitiy就有可能被启动。
下面通过一个简单的示例来示范Action属性(就是普通字符串)的作用。下面程序的第一个Activity非常简单,它只包括一个普通按钮,当用户单击该按钮时,程序会“跳转”到第二个Activity。但第一个Activity指定跳转的Intent时,并不指定要跳转的目标Activity,而是为Intent指定Action属性。此处不给出界面布局的代码,第一个Activity 的Java代码如下:
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
上面程序中的onClick回调方法里面的代码指定了根据Intent来启动Activity。但该Intent并未指定要启动哪个Activity,从上面程序中的代码无法看出该程序将要启动哪个Activity。那么到底程序会启动哪个Activity呢?这取决于Activity配置中 <intent-fiIter.../>元素的配置。
<intent-filter.../>元素是 AndroidManifest.xml 文件中<activity.../>元素的子元素,前面已经学习过,<activity.../>元素用于为应用程序配置 Activity,<activity.../>的<intent-filter.../>子元素则用于配置该Activity所能“响应”的Intent。
<intent-filter.../>元素里通常可包含如下子元素。
· 0〜N个<action.../>子元素。
· 0〜N个<category…/>子元素。
· 0〜1个<data.../>子元素。
<action.../>、<category.../>子元素的配置非常简单,它们都可指定android:name属性,该属性的值就是一个普通字符串。当<activity.../>元素的<intent-fiIter.../>子元素里包含多个<action.../>子元素(相当于指定了多个字符串)时,就表明该Activity能响应Action属性值为其中任意一个字符串的Intent。
由于上面的程序指定启动Action属性为MainActivity.TEST_ACTION常量的 Activity,也就要求被启动的 Activity 对应的配置元素的<intent-filter.../>元素里至少包括一个<action.../>子元素。另外上面程序中的代码并未指定目标Intent的Category属性,但该Intent 已有一个值为 android.intent.category.DEFAULT 的 Category 属性值,因此被启动 Activity 对应的配置元素的<intent-filter.../>元素里至少还包括一个如下的<category.../>子元素。被启动的Activity的完整配置如下:
[代码]xml代码:
1 2 3 4 5 6 7 8 9 |
|
上面Activity配置的代码指定该Activity能响应具有指定Action属性值、默认 Category属性值的Intent。其中有一行代码只是试验用的,对于本程序没有影响——它表明该Activity能响应Action属性值为helloWorld字符串、Category属性值为 android.intent.category.DEFAULT的Intent,但我们的程序并未尝试启动这样的Activity,可以自己尝试用这样的Intent来启动Activity,将会看到程序也会启动该Activity。
上面的配置代码中配置了一个实现类为SecondActivity的Activity,因此程序还应该提供这个Activity代码。代码如下:
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 |
|
上面的程序代码很简单,它只是在启动时把启动该Activity的Intent的Action属性值显示在指定文本框内。
运行上面的程序,单击程序中的“启动指定 Action、默认Category对应的Activity”按钮,将看到下图所示界面。
实际上Android内部提供了大量标准的Action常量,其中用于启动Activity的标准的Action常量及对应的字符串如下表所示。