Intent 介紹
Intent 是 Android 程序中各組件之間進(jìn)行交互的一種重要方式歇终,它不僅可以指明當(dāng)前組件想要執(zhí)行的動(dòng)作社证,還可以在不同組件間傳遞數(shù)據(jù)。Intent 一般被用于啟動(dòng)活動(dòng)评凝、啟動(dòng)服務(wù)追葡、或是發(fā)送廣播等場(chǎng)景。Intent 的用法大致分為兩種奕短,顯式 intent 和隱式 intent宜肉。<br />
既然需要涉及到第二個(gè) Activity,那我們就先來(lái)創(chuàng)建一個(gè)新的 Activity篡诽,命名為 SecondActivity.
- Step 1 新建 second_layout.xml 文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 2"/>
</LinearLayout>
- Step 2 新建活動(dòng) SecondActivity 繼承自 Activity
public class SecondActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.second_layout);
}
}
- Step 3 在 AndroidManifest.xml 中為 SecondActivity 注冊(cè)
<activity android:name=".SecondActivity">
</activity>
顯式 Intent
Intent 有多個(gè)構(gòu)造函數(shù)的重載崖飘,其中一個(gè)是 Intent(Context packageContext,Class<?>cls),這個(gè)構(gòu)造函數(shù)接受兩個(gè)參數(shù)榴捡,第一個(gè) Context 是提供一個(gè)啟動(dòng)活動(dòng)的上下文杈女,第二個(gè)參數(shù) Class 是指定想要啟動(dòng)的目標(biāo)活動(dòng)。通過(guò)此函數(shù)可以構(gòu)建出 Intent 的“意圖”吊圾。Activity 類中提供了一個(gè) startActivity() 方法达椰,此方法用于啟動(dòng)活動(dòng),它接收一個(gè) Intent 參數(shù)项乒。<br />
修改 FirstActivity 中按鈕的點(diǎn)擊事件啰劲,代碼如下:
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
}
});
使用這種方式來(lái)啟動(dòng)活動(dòng),Intent 的意圖很明顯檀何,所以稱為顯式 Intent蝇裤。
隱式 Intent
并不明確指出我們想要啟動(dòng)哪一個(gè)活動(dòng),而是指定了一系列更抽象的 action 和 category 等频鉴,然后又系統(tǒng)去分析這個(gè) Intent 并幫我們找到合適的活動(dòng)去啟動(dòng)栓辜。
- 配置 AndroidManifest.xml 中 <activity> 標(biāo)簽下 <intent-filter> 中的 <action> 和 <category> 可以指定當(dāng)前活動(dòng)能夠相應(yīng)的 action 和 category。
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
- 修改 FirstActivity 中按鈕的點(diǎn)擊事件垛孔,使 SecondActivity 能夠響應(yīng)藕甩。
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.activitytest.ACTION_START");
startActivity(intent);
}
});
為什么這里沒(méi)有指定 category 呢?因?yàn)?android.intent.category.DEFAULT 是一種默認(rèn)的 category周荐,startActivity() 方法會(huì)自動(dòng)把 category 添加到 Intent 中狭莱。<br />
每個(gè) Intent 中只能指定一個(gè) action僵娃,但卻能夠指定多個(gè) category。
- 再為 SecondActivity 添加一個(gè) category腋妙。
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.example,activitytest.MY_CATEGORY"/>
</intent-filter>
</activity>
- 再次修改 FirstActivity 中按鈕的點(diǎn)擊事件默怨,使 SecondActivity 能夠響應(yīng)。
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.activitytest.ACTION_START");
intent.addCategory("com.example,activitytest.MY_CATEGORY");
startActivity(intent);
}
});
調(diào)用 Intent 中的 addCategory() 方法來(lái)添加一個(gè) category辉阶,這樣 SecondActivity 就能夠正常響應(yīng)了先壕。
更多的隱式 Intent 用法
- 修改 FirstActivity 中按鈕的點(diǎn)擊事件,使之能夠通過(guò)系統(tǒng)自帶的瀏覽器打開(kāi)網(wǎng)頁(yè)谆甜。
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
Intent 的 action 是一個(gè) Android 系統(tǒng)內(nèi)置的動(dòng)作垃僚,常量值為 android.intent.action.VIEW。然后通過(guò) Uri.parse() 方法规辱,將一個(gè)網(wǎng)址字符串解析成一個(gè) Uri 對(duì)象谆棺,再調(diào)用 Intent 的 setData() 方法把 Uri 對(duì)象傳遞進(jìn)去。setDate() 方法接收一個(gè) Uri 對(duì)象罕袋,主要用于指定當(dāng)前 Intent 正在操作的數(shù)據(jù)改淑,數(shù)據(jù)通常是以字符串形式傳遞到 Uri.parse() 方法中解析產(chǎn)生。
<data> 標(biāo)簽的使用
在 <intent-filter> 標(biāo)簽中再配置一個(gè) <data> 標(biāo)簽浴讯,可用于更精準(zhǔn)的指定當(dāng)前活動(dòng)能夠響應(yīng)什么類型的數(shù)據(jù)朵夏。<data> 標(biāo)簽主要可以配置以下內(nèi)容:
- android:scheme <br />
用于指定數(shù)據(jù)協(xié)議部分 - android:host <br />
用于指定數(shù)據(jù)主機(jī)名部分 - android:port <br />
用于指定數(shù)據(jù)端口部分 - android:path <br />
用于指定主機(jī)名和端口之后部分 - android:mimeType <br />
用于指定可以處理的數(shù)據(jù)類型
只有 <data> 標(biāo)簽中指定的內(nèi)容和 Intent 中攜帶的 Data 完全一致時(shí),當(dāng)前活動(dòng)才能夠響應(yīng)該 Intent榆纽。例如:
- 新建 third_layout.xml 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 3"/>
</LinearLayout>
- 新建活動(dòng) ThirdActivity 繼承自 Activity
public class ThirdActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.third_layout);
}
}
- 在 AndroidManifest.xml 中為 ThirdActivity 注冊(cè)
<activity android:name=".ThirdActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
</intent-filter>
</activity>
此時(shí)運(yùn)行點(diǎn)擊 FirstActivity 的按鈕會(huì)彈出一個(gè)列表仰猖,讓你選擇是用自帶瀏覽器打開(kāi)還是使用新建的 ThirdActivity 打開(kāi)。
調(diào)用系統(tǒng)撥號(hào)界面
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
});
向下一個(gè)活動(dòng)傳遞數(shù)據(jù)
啟動(dòng)活動(dòng)時(shí)傳遞數(shù)據(jù)思路很簡(jiǎn)單奈籽,Intent 中提供了一系列的 putExtra() 方法的重載饥侵,把想要傳遞的數(shù)據(jù)暫存在 Intent 中,啟動(dòng)另一個(gè)活動(dòng)后衣屏,再把數(shù)據(jù)從 Intent 中取出來(lái)躏升。
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String data = "Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("extra_data",data);
startActivity(intent);
}
});
putExtra() 方法接收兩個(gè)參數(shù),第一個(gè)是鍵狼忱,第二個(gè)是值膨疏。
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.second_layout);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
}
在 SecondActivity 中將傳遞的數(shù)據(jù)取出,并打印出來(lái)钻弄。通過(guò) getIntent() 方法獲取用于啟動(dòng) SecondActivity 的 Intent 佃却,然后調(diào)用 getStringExtra() 方法取出數(shù)據(jù)。
返回?cái)?shù)據(jù)給上一活動(dòng)
Activity 中有一個(gè) startActivityForResult() 方法也用于啟動(dòng)活動(dòng)斧蜕,但這方法期望在活動(dòng)銷毀時(shí)返回一個(gè)結(jié)果給上一個(gè)活動(dòng)双霍。
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivityForResult(intent,1);
}
});
使用 startActivityForResult() 方法來(lái)啟動(dòng) SecondActivity ,startActivityForResult() 方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)是 Intent洒闸,第二個(gè)參數(shù)是請(qǐng)求碼染坯,用于在回調(diào)中判斷數(shù)據(jù)來(lái)源。
- 為 SecondActivity 按鈕注冊(cè)點(diǎn)擊事件丘逸,添加返回?cái)?shù)據(jù)邏輯
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.putExtra("data_return","Hello FirstActivity");
setResult(RESULT_OK,intent);
finish();
}
});
setResult() 方法專門(mén)用于向上一個(gè)活動(dòng)返回?cái)?shù)據(jù)单鹿,接收兩個(gè)參數(shù),第一個(gè)是向上一個(gè)活動(dòng)返回處理結(jié)果深纲,第二個(gè)參數(shù)是把帶有數(shù)據(jù)的 Intent 傳遞回去仲锄,然后調(diào)用 finish() 方法銷毀當(dāng)前活動(dòng)。<br />
使用 startActivityForResult() 方法來(lái)啟動(dòng) SecondActivity湃鹊,在 SecondActivity 銷毀之后會(huì)回調(diào)上一個(gè)活動(dòng)的 onActivityResult() 方法儒喊,所以需在 FristActivity 上重寫(xiě)這個(gè)方法來(lái)獲取數(shù)據(jù)。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 1:
if (resultCode == RESULT_OK){
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity",returnedData);
}
break;
default:
}
}
onActivityResult() 方法帶有三個(gè)參數(shù)币呵,第一個(gè)是啟動(dòng)活動(dòng)時(shí)傳入的請(qǐng)求碼怀愧,第二個(gè)是返回時(shí)的處理結(jié)果,第三個(gè)是攜帶返回?cái)?shù)據(jù)的 Intent余赢。<br /><br />
如果用戶點(diǎn)擊的是 Back 鍵芯义,而不是點(diǎn)擊按鈕怎么辦?重寫(xiě) onBackPressed() 方法妻柒。
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("data_return","Hello FirstActivity");
setResult(RESULT_OK,intent);
finish();
}