Android Intent
Android
应用程序内不同组件之间的通信载体。
Intent
封装了当前组件需要启动或触发的目标组件的信息。
**优点1:**提供一致的编程模型封装“启动意图”,无论是对 Activity
、Service
、BroadcastReceiver
来说都一致。
**优点2:**利于高层次解耦,在程序只想启动具有某种特征的组件,不想和某个具体的组件耦合时可以使用 Intent
。
包含如下属性:
- Component:明确指定需要启动的目标组件。
- Action:该
Intent
所要完成的一个抽象动作
。 - Category:为
Action
增加额外的附加类别信息。 - Data:向
Action
提供操作的数据。 - Type:指定
Data
属性所指定的Uri
对应的MIME
类型。 - Extra:携带需要交换的数据,在多个
Action
之间进行数据交换,属性值是一个Bundle
对象(类似Map
对象)。 - Flag:用于未该
Intent
添加一些额外的控制旗标。
使用 Intent
启动不同组件方法
组件类型 | 启动方法 |
---|---|
Activity | startActivity(Intent intent) |
Activity | startActivityForResule(Intent intent, int requestCode) |
Service | ComponentName startService(Intent service) |
Service | boolean bindService(Intent service, ServiceConnection conn, int flags) |
BroadcastReceiver | sendBroadcast(Intent intent) |
BroadcastReceiver | sendBroadcast(Intent intent, String receiverPermission) |
BroadcastReceiver | sendOrderBroadcast(Intent intent, String receiverPermission) |
BroadcastReceiver | sendOrderBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) |
BroadcastReceiver | sendStickyBroadcast(Intent intent) |
BroadcastReceiver | sendStickyOrderedBroadcast9Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) |
页面跳转及传参
利用 Intent
:
// Activiy1
String string1 = "...";
String string2 = "...";
Intent intent = new Intent(Activity1.this, Activity2.class);
// 上述语句是下面语句的简写形式:
// ComponentName comp = new ComponentName(Activity1.this, Activity2.class);
// Intent intent = new Intent();
// intent.setComponent(comp);
intent.putExtra("param1", string1);
intent.putExtra("param2", string2);
startActivity(intent);
// Activity2
Intent intent = getIntent();
String param1 = intent.getExtra("param1");
String param2 = intent.getExtra("param2");
利用 Bundle
:
// Activity1
String string1 = "...";
String string2 = "...";
Intent intent = new Intent(Activity1.this, Activity2.class);
BUndle bundle = new Bundle();
bundle.putString("param1", string1);
bundle.putStirng("param2", string2);
intent.putExtras(bundle);
startActivity(intent);
// Activity2
Bundle bundle = this.getIntent().getExtras();
String param1 = bundle.getString("param1");
String param2 = bundle.getStirng("param2");
Component
需接受一个 ComponentName
对象,而创建此对象需要指定包名与类名,这样才可以唯一确定一组件类。这样应用程序可以根据给定的组件类去启动特定的组件。
指定 Component
属性的 Intent
被称为 显式Intent
;没有指定 Component
属性的 Intent
被称为 隐式Intent
,没有明确启动的组件,需要根据制定规则去启动符合的组件。
Action
Category
与 <intent-filter>
配置
Intent
通过指定 Action
属性值(某一字符串),可以把该 Intent
与具体 Activity
分离,提供高层次解耦。
每个 Intent
只能指定一个 Action
,但可以指定多个 Category
。IntentFilter
用于声明该组件能满足的要求,每个组件可以声明自己满足多个 Action
与 Category
。只要某个组件能满足的要求大于等于 Intent
所指定的要求,那么该 Intent
就可以启动该组件。
Intent
对象可以通过 Android
内部提供的标准的 Action
、Category
常量启动 Android
系统的其他停用的程序组件,包括系统自带的程序组件(需要权限允许)。
<intent-filter.../>
中可包含如下子元素:
- 0~N个
<action.../>
子元素 - 0~N个
<category.../>
子元素 - 0~1个
<data.../>
子元素
<activity android:name=".SecondActivity"
android:label="Second-Activity"/>
<intent-filter>
<!-- 该Activity能响应Action属性值为指定字符串的Intent -->
<action android:name="..."/>
<action android:name="..."/>
<!-- 当创建Intent时,该Intent默认添加一个值为Intent.CATEGORY_DEFAULT的Category属性值 -->
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
// 设置Action属性
publiv static final String SECOND_ACTION = "SECOND_ACTION";
intent.setAction(SecondActivity.SECOND_ACTION);
// 添加Category属性
intent.addCategory("SECOND_CATEGORY");
// 在程序中通过如下代码查看该Activity对应的Intent的Action属性值与Category属性值:
Sting action = getIntent().getAction();
Set<String> Category = getInstent().getCategories();
// 调起系统应用-联系人
intent.setAction(Intent.ACTION_PICK);
intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
startActivityForResult(intent, PICK_CONTACT);
// 返回系统桌面
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
Data
Type
与 <intent-filter>
配置
Date属性接受一个Uri对象,通常通过如下形式字符串表示:
// 格式
scheme://host:port/path
// 示例
content://com.android.contacts/contacts/1
tel:123
Type
属性用于指定 Data
属性所指定 Uri
对应的 MIME
类型,这种 MIME
类型可以是任何自定义的 MIME
类型,只要符合 abc/xyz
格式的字符串即可。
Data
属性会与 Type
属性相互覆盖:
- 先设置Data属性,后设置Type属性,Type属性将覆盖Data属性;
- 先设置Type属性,后设置Data属性,Data属性将覆盖Type属性;
- 调用
setDataAndType()
方法,同时设置Data属性与Type属性。
// 设置Type属性
intent.setType("abc/xyz");
// 设置Data属性
intent.setData(Uri.parse("scheme://host:port/path"));
// 同时设置Data与Type属性
intent.setDataAndType(Uri.parse("scheme://host:port/path"), "abc/xcy");
在 AndroidManifest.xml
文件中为组件声明 Data
、 Type
属性都通过 <data.../>
元素:
<data android:mimeType=""
android:scheme=""
android:host=""
android:port=""
android:path=""
android:pathPrefis=""
android:pathPattern="" />
其中:
- mimeType:用于声明该组件所能匹配的Intent的
Type
属性; - scheme:用于声明该组件所能匹配的Intent的Data属性的
scheme
部分; - host:用于声明该组件所能匹配的Intent的Data属性的
host
部分; - port:用于声明该组件所能匹配的Intent的Data属性的
port
部分; - path:用于声明该组件所能匹配的Intent的Data属性的
path
部分; - pathPrefix:用于声明该组件所能匹配的Intent的Data属性的
path
前缀; - pathPattern:用于声明该组件所能匹配的Intent的Data属性的
path
字符串模板。
匹配时Intent的Type属性需要与 <intent-filter>
中 <data.../>
的mimeType属性相同。
匹配时Intent的Data属性,不一定需要完全满足,只要Intent中Data属性的Uri与 <intent-filter>
的 <data.../>
属性匹配下述中任何一种,即可打开该组件:
- scheme
- scheme、host
- scheme、host、port
- scheme、host、path
- shceme、host、port、path
Flag属性
用于为该Intent添加一些额外的控制旗标,调用 addFlags()
方法添加控制旗标。一些常用的Flag属性如下:
属性 | 作用 |
---|---|
FLAG_ACTIVITY_BROUGHT_TO_FRONT | 如果通过该Flag启动的Activity已经存在,下次再次启动时,将只是将该Activity带到前台。例如现在Activity栈中有Activity A,此时以该Flag启动Activity B(即Activity B是以FLAG_ACTIVITY_BROUGHT_TO_FRONT旗标启动的),然后在Activity B中启动C、D,这时Activity栈中的情形是A、B、C、D。如果此时在Activity D中再启动B,将直接把Activity栈中的Activity B带到前台。此时Activity栈中的情形是A、C、D、B。 |
FLAG_ACTIVITY_CLEAR_TOP | 该Flag相当于加载模式中的singleTask,通过这种Flag启动的Activity将会把要启动的Activity之上的Activity全部弹出Activity栈。例如,Activity栈中包含A、B、C、D这四个Activity,如果采用该Flag从Activity D跳转到Activity B,此时Activity栈中只包含A、B两个Activity。 |
FLAG_ACTIVITY_NEW_TASK | 默认的启动旗标。该旗标控制重新创建一个新的Activity。 |
FLAG_ACTIVITY_NO_ANIMATION | 该旗标会控制启动Activity时不适用过渡动画。 |
FLAG_ACTIVITY_NO_HISTORY | 该旗标控制被启动的Activity将不会保留在Activity栈中。例如Activity中原有A、B、C三个Activity,此时在Activity C中以该Flag启动Activity D,Activity D再启动Activity E,此时Activity栈中只有A、B、C、E这4个Activity,Activity D不会保留在Activity栈中。 |
FLAG_ACTIVITY_REORDER_TO_FRONT | 该Flag控制如果当前已有该Activity,直接将该Activity带到前台。例如现在Activity栈中有A、B、C、D这4个Activity,如果使用该Flag来启动Activity B,那么启动后的Activity栈中情形为A、C、D、B。 |
FLAG_ACTIVITY_SINGLE_TOP | 该Flag相当于加载模式中的singleTop模式,例如原来Activity栈中有A、B、C、D这四个Activity,在Activity D中再次启动Activity D,那么Activity栈中还是A、B、C、D这四个Activity。 |