Intent
Intent 是 Android 中的各個(gè)組件之間交互的一種重要方式,它可以用來(lái)啟動(dòng) Activity、Service 和 BroadcastReceiver,還可以在不同組件之間傳遞數(shù)據(jù)。
Intent Filter
- Intent Filter 就是用來(lái)注冊(cè) Activity 、 Service 和 Broadcast Receiver 具有能在某種數(shù)據(jù)上執(zhí)行一個(gè)動(dòng)作的能力。使用 Intent Filter,應(yīng)用程序組件告訴 Android,它們能為其它程序的組件的動(dòng)作請(qǐng)求提供服務(wù),包括同一個(gè)程序的組件、本地的或第三方的應(yīng)用程序?!?Android開(kāi)發(fā)--Intent-filter屬性詳解
- Intent Filter 負(fù)責(zé)過(guò)濾掉組件本身無(wú)法響應(yīng)和處理的 Intent,只將自己關(guān)心的 Intent 接收進(jìn)來(lái)進(jìn)行處理。—— IntentFilter
Intent 的七大屬性
- ComponentName: 指定了 ComponentName 屬性的 Intent已經(jīng)明確了它將要啟動(dòng)哪個(gè)組件,這種 Intent 被稱(chēng)為顯式 Intent;沒(méi)有指定 ComponentName 屬性的 Intent 被稱(chēng)為隱式 Intent。隱式Intent沒(méi)有明確要啟動(dòng)哪個(gè)組件,應(yīng)用會(huì)根據(jù) Intent 指定的規(guī)則去啟動(dòng)符合條件的組件。
- Action: Action 屬性用于指定要執(zhí)行的動(dòng)作,一個(gè) Intent 只能設(shè)置一個(gè) Action。
- Category: Category 屬性為 Action 增加額外的附加類(lèi)別信息。CATEGORY_LAUNCHER 意味著在加載程序的時(shí)候 Acticity 出現(xiàn)在最上面,而 CATEGORY_HOME 表示頁(yè)面跳轉(zhuǎn)到 HOME 界面。一個(gè) Intent 可以添加多個(gè) Category。
-
Data: Data 屬性通常用于向 Action 屬性提供操作的數(shù)據(jù)。Data 屬性的值是個(gè) Uri 對(duì)象。
Uri 的格式如下:scheme://host:port/path
- scheme:用于指定數(shù)據(jù)的協(xié)議部分,如 http
- host:用于指定數(shù)據(jù)的主機(jī)名部分,如 www.google.com
- port:用于指定數(shù)據(jù)的端口部分,跟在主機(jī)后面,可以省略
- path:用于指定主機(jī)名和端口之后的部分,通常是資源的路徑,可以省略 - Type: Type 屬性用于指定 Data 所指定的 Uri 對(duì)應(yīng)的 MIME 類(lèi)型。MIME 只要符合 “abc/xyz” 這樣的字符串格式即可。
- Extras: Extras 屬性用于保存需要傳遞的額外數(shù)據(jù)。
- Flag: Intent 可調(diào)用 addFlags() 方法來(lái)為 Intent 添加控制標(biāo)記。
AndroidManifest.xml 中的 <intent-filter> 標(biāo)簽
<intent-filter> 標(biāo)簽可以包含以下三個(gè)元素:
- <action>: 一個(gè) <intent-filter> 可以有一個(gè)或多個(gè) <action> 用于過(guò)濾,到達(dá)的 Intent 只需要匹配其中一個(gè) <action> 即可。
- <category>: 一個(gè) <intent-filter> 中可以有多個(gè) <category>,只有 Intent 中的所有 Category 都能匹配到 <intent-filter> 中的 <category> 時(shí),Intent 才能通過(guò)檢查。
-
<data>: <data> 元素包含的內(nèi)容為 Uri 和數(shù)據(jù)類(lèi)型,<data> 元素中一般不會(huì)指定過(guò)多的內(nèi)容。
- Uri 格式見(jiàn)上面。
- mimeType:用于指定可以處理的數(shù)據(jù)類(lèi)型,可以省略。 - 更多內(nèi)容,請(qǐng)看這篇文章 IntentFilter
Intent 的用法 - 啟動(dòng)組件
Intent 啟動(dòng)組件的方法可以分為兩種,分別是顯式 Intent 和 隱式 Intent。顯式 Intent 必須明確指出要啟動(dòng)的是哪個(gè)組件;隱式 Intent 只須指出想要啟動(dòng)的組件的特征,系統(tǒng)就會(huì)自動(dòng)啟動(dòng)符合該特征的組件。
啟動(dòng)組件 - 使用顯式 Intent
這里我們以從一個(gè) Activity 跳轉(zhuǎn)到 另一個(gè) Activity 為例。
1.?XML 布局文件:
- activity_first.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:context=".FirstActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="這是第一個(gè)Activity" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startSecondActivity"
android:text="啟動(dòng)第二個(gè)Activity" />
</LinearLayout>
- activity_second.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="這是第二個(gè)Activity" />
</LinearLayout>
2.?Java 代碼:
- FirstActivity.java
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
}
public void startSecondActivity(View view) {
// 第一個(gè)參數(shù)為當(dāng)前上下文,第二個(gè)參數(shù)為要啟動(dòng)的組件
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
}
}
- SecondActivity.java
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
}
- 不要忘了在清單文件 AndroidManifest.xml 中注冊(cè)第二個(gè) Activity:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.monkeychan.intenttest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".FirstActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity"></activity>
</application>
</manifest>
- 效果演示:

點(diǎn)擊按鈕,啟動(dòng)第二個(gè) Activity

啟動(dòng)組件 - 使用隱式 Intent
下面我們使用隱式 Intent 來(lái)實(shí)現(xiàn)上面的跳轉(zhuǎn)效果。
1.?首先修改 AndroidManifest.xml 成如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.monkeychan.intenttest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".FirstActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="net.monkeychan.intenttest.action.START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
可以看到,我們給 SecondActivity 配置了 intent-filter,并在 intent-filter 下增加了 action 屬性和 category 屬性。
2.?Java 代碼,這里只須修改 FirstActivity.java:
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
}
public void startSecondActivity(View view) {
Intent intent = new Intent("net.monkeychan.intenttest.action.START");
startActivity(intent);
}
}
- 效果演示:
效果與上面使用顯式 Intent 方式啟動(dòng)一樣,只不過(guò)這里是使用隱式 Intent 方式實(shí)現(xiàn)罷了。
使用隱式 Intent 啟動(dòng)系統(tǒng)組件
使用隱式隱式 Intent 除了可以啟動(dòng)同一個(gè)應(yīng)用程序的組件,還可以啟動(dòng)系統(tǒng)或第三方應(yīng)用程序的組件。下面使用隱式 Intent 來(lái)啟動(dòng)系統(tǒng)的組件。
1. 啟動(dòng)撥號(hào)界面
- XML 布局文件,activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:context=".MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="啟動(dòng)撥號(hào)界面"
android:onClick="startDial"/>
</LinearLayout>
- Java 代碼,MainActivity.java:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startDial(View view) {
// 1. 創(chuàng)建一個(gè) Intent 對(duì)象
Intent intent = new Intent();
// 2. 設(shè)置 Intent 對(duì)象的 Action
// ACTION_DIAL 是 Intent 中定義的一個(gè)常量,查源碼可知:
// public static final String ACTION_DIAL = "android.intent.action.DIAL";
// 這是 Android 中已經(jīng)定義好的,事實(shí)上 Intent 中還有許多這樣的常量
intent.setAction(Intent.ACTION_DIAL);
// 3. 跳轉(zhuǎn)到對(duì)應(yīng)的組件
startActivity(intent);
}
}
- AndroidManifest.xml 文件,記得聲明權(quán)限,這里的權(quán)限是使用電話:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.monkeychan.intenttest">
<!-- 聲明該應(yīng)用需要使用電話 -->
<uses-permission android:name="android.permission.CALL_PHONE">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</uses-permission>
</manifest>
上面的代碼實(shí)現(xiàn)的功能是這樣的:當(dāng)我們點(diǎn)擊按鈕時(shí),將會(huì)跳轉(zhuǎn)到撥號(hào)界面。
- 效果演示:

點(diǎn)擊按鈕,將會(huì)跳轉(zhuǎn)到撥號(hào)界面:

接下來(lái)我們對(duì)上面的程序進(jìn)行修改,當(dāng)點(diǎn)擊按鈕時(shí),將會(huì)把我們要撥打的號(hào)碼自動(dòng)寫(xiě)好,我們只須按下?lián)芴?hào)鍵就可以撥打了。
- XML 布局文件以及 AndroidManifest.xml 文件無(wú)須修改, Java 代碼部分修改成如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startDial(View view) {
// 1. 創(chuàng)建一個(gè) Intent 對(duì)象
Intent intent = new Intent();
// 2. 設(shè)置 Intent 對(duì)象的 Action
// ACTION_DIAL 是 Intent 中定義的一個(gè)常量,查源碼可知:
// public static final String ACTION_DIAL = "android.intent.action.DIAL";
// 這是 Android 中已經(jīng)定義好的,事實(shí)上 Intent 中還有許多這樣的常量
intent.setAction(Intent.ACTION_DIAL);
// tel 是 Android 中已經(jīng)定義好的,用于撥打電話,這里設(shè)置要撥打的號(hào)碼為 10010
Uri uri = Uri.parse("tel://10010");
// 3. 調(diào)用 Intent 對(duì)象的 setData() 方法,該方法需要傳入一個(gè) Uri 類(lèi)型的參數(shù)
intent.setData(uri);
// 4. 跳轉(zhuǎn)到對(duì)應(yīng)的組件
startActivity(intent);
}
}
-
效果演示:
點(diǎn)擊按鈕之后,號(hào)碼將自動(dòng)寫(xiě)好:

2. 發(fā)送短信
- XML 布局文件,activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:context=".MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="發(fā)送短信"
android:onClick="sendSMS"/>
</LinearLayout>
- Java 代碼,MainActivity.java:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void sendSMS(View view) {
// 1. 創(chuàng)建一個(gè) Intent 對(duì)象
Intent intent = new Intent();
// 2. 設(shè)置 Intent 對(duì)象的 Action
intent.setAction(Intent.ACTION_VIEW);
// smsto 是 Android 中已經(jīng)定義好的,用于發(fā)送,這里設(shè)置要發(fā)送的號(hào)碼為 10010
Uri uri = Uri.parse("smsto://10010");
// 3. 設(shè)置 Intent 對(duì)象的 setData() 方法,該方法需要傳入一個(gè) Uri 類(lèi)型的參數(shù)
intent.setData(uri);
// 4. 設(shè)置短信的內(nèi)容,調(diào)用 Intent 對(duì)象的 putExtra() 方法,該方法需要傳入一個(gè)鍵值對(duì)(key-value)
// 其中 key 為 sms_body,是 Android 系統(tǒng)已經(jīng)定義好的,系統(tǒng)的短信發(fā)送程序只能識(shí)別 sms_body
intent.putExtra("sms_body", "CXYE");
// 5. 跳轉(zhuǎn)到對(duì)應(yīng)的組件
startActivity(intent);
}
}
- 聲明權(quán)限,這里的權(quán)限是發(fā)送短信,AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.monkeychan.intenttest">
<uses-permission android:name="android.permission.SEND_SMS"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity"></activity>
</application>
</manifest>
- 效果演示:

點(diǎn)擊按鈕,啟動(dòng)發(fā)送短信程序,并將我們要發(fā)送的號(hào)碼及內(nèi)容傳遞給系統(tǒng)短信程序

點(diǎn)擊發(fā)送按鈕:

注意,這里使用的是虛擬機(jī),實(shí)際上并沒(méi)有給10010發(fā)送短信。
總結(jié):使用 Intent 啟動(dòng) Activity 的步驟
- 創(chuàng)建一個(gè) Intent 對(duì)象;
若是顯式啟動(dòng)直接向構(gòu)造方法里傳入源 Activity 和 目的 Activity,然后進(jìn)行第 3 步:
Intent intent = new Intent(OriActivity.this, DesActivity.class);
若是隱式啟動(dòng)直接調(diào)用無(wú)參的構(gòu)造方法:
Intent intent = new Intent();
- 根據(jù)具體對(duì) Intent 對(duì)象進(jìn)行設(shè)置,如設(shè)置 Action、添加 Category 、設(shè)置 Data 等
等;
intent.setAction("MyAction");
intent.addCategory("MyCategory");
intent.setData(Uri.parse("scheme://host"));
- 跳轉(zhuǎn)到相應(yīng)的 Activity。
startActivity(intent);
Intent 的用法 - 傳遞數(shù)據(jù)
Intent 除了可以用來(lái)啟動(dòng)各種組件之外,還可以用來(lái)在組件之間傳遞數(shù)據(jù)。
使用 Intent 在 Activity 之間傳遞數(shù)據(jù)
1. 傳遞簡(jiǎn)單數(shù)據(jù)
我們來(lái)做一個(gè)實(shí)現(xiàn)注冊(cè)功能的程序:用戶在注冊(cè)界面填寫(xiě)用戶名和密碼,之后點(diǎn)擊注冊(cè)按鈕,跳轉(zhuǎn)到注冊(cè)成功界面,該界面提示用戶注冊(cè)成功,并顯示用戶的注冊(cè)信息。
1.?XML 布局文件
- 注冊(cè)界面,activity_signup.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="用戶名:" />
<EditText
android:id="@+id/et_userName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請(qǐng)輸入用戶名" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_userPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密碼:" />
<EditText
android:id="@+id/et_userPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請(qǐng)輸入密碼" />
</TableRow>
<Button
android:id="@+id/btn_signUp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="注冊(cè)"
android:onClick="signUp"/>
</LinearLayout>
- 注冊(cè)成功界面,activity_signup_success.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tv_userName"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_userPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
2.?Java 代碼
- 注冊(cè)界面,SignUpActivity.java:
public class SignUpActivity extends AppCompatActivity {
private EditText et_userName;
private EditText et_userPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
// 設(shè)置 title
setTitle("注冊(cè)界面");
initView();
}
// 該方法用于實(shí)例化布局中的控件
private void initView() {
et_userName = (EditText) findViewById(R.id.et_userName);
et_userPassword = (EditText) findViewById(R.id.et_userPassword);
}
public void signUp(View view) {
// 獲取 EditText 里的數(shù)據(jù)
String userName = et_userName.getText().toString();
String userPassword = et_userPassword.getText().toString();
// 1. 創(chuàng)建一個(gè) Intent 對(duì)象,并傳入將要啟動(dòng)的 Activity
Intent intent = new Intent(SignUpActivity.this, SignUpSuccessActivity.class);
// 2. 往 Intent 的對(duì)象里放入需要傳遞的數(shù)據(jù)
intent.putExtra("userName", userName);
intent.putExtra("userPassword", userPassword);
// 3. 啟動(dòng)相應(yīng)的組件,并將數(shù)據(jù)傳遞過(guò)去
startActivity(intent);
}
}
- 注冊(cè)成功界面,SignUpSuccessActivity.java:
public class SignUpSuccessActivity extends AppCompatActivity {
private TextView tv_userName;
private TextView tv_userPassword;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup_success);
// 設(shè)置 title
setTitle("注冊(cè)成功");
initView();
display();
}
// 該方法用來(lái)顯示用戶的注冊(cè)信息
private void display() {
//1. 獲取啟動(dòng)本 Activity 的 Intent
intent = getIntent();
// 2. 從 Intent 中取出數(shù)據(jù),根據(jù)鍵取出相應(yīng)的值
// 注意,此鍵要與傳遞過(guò)來(lái)的鍵一致,否則會(huì)出現(xiàn) NullPointerException 異常
String userName = intent.getStringExtra("userName");
String userPassword = intent.getStringExtra("userPassword");
// 3. 顯示用戶的注冊(cè)信息
tv_userName.setText("您的用戶名為:" + userName);
tv_userPassword.setText("您的注冊(cè)密碼為:" + userPassword);
}
// 該方法用來(lái)實(shí)例化布局中的控件
private void initView() {
tv_userName = (TextView) findViewById(R.id.tv_userName);
tv_userPassword = (TextView) findViewById(R.id.tv_userPassword);
}
}
3.?最后,在 AndroidManifest.xml 中注冊(cè):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.monkeychan.intenttest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".SignUpActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SignUpSuccessActivity"></activity>
</application>
</manifest>
4)?效果演示:

輸入用戶名和密碼:

點(diǎn)擊注冊(cè)按鈕:

返回?cái)?shù)據(jù)給上一個(gè) Activity
除了向下一個(gè) Activity 傳遞數(shù)據(jù),下一個(gè) Activity 也可以向上一個(gè) Activity 傳遞數(shù)據(jù),具體步驟如下:
- 上一個(gè) Activity 在跳轉(zhuǎn)到相應(yīng)的 Activity 時(shí)調(diào)用 startActivityForResult(Intent intent, int requestCode) 方法;
- 在下一個(gè) Activity 調(diào)用 setResult(int resultCode, Intent data) 方法;
- 重寫(xiě)上一個(gè) Activity 中的 onActivityResult(int requestCode, int resultCode, Intent data) 方法,在此方法中根據(jù) resultCode 和 resultCode 對(duì)對(duì)應(yīng)的返回?cái)?shù)據(jù)進(jìn)行處理。
注意:requestCode 必須是唯一的,resultCode 也必須是唯一的,但兩者可以相同。
修改上面的程序中 Java 部分的代碼如下:
- SignUpActivity.java:
public class SignUpActivity extends AppCompatActivity {
private EditText et_userName;
private EditText et_userPassword;
private Button btn_signUp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
// 設(shè)置 title
setTitle("注冊(cè)界面");
initView();
}
// 該方法用于實(shí)例化布局中的控件
private void initView() {
et_userName = (EditText) findViewById(R.id.et_userName);
et_userPassword = (EditText) findViewById(R.id.et_userPassword);
btn_signUp = (Button) findViewById(R.id.btn_signUp);
}
public void signUp(View view) {
// 獲取 EditText 里的數(shù)據(jù)
String userName = et_userName.getText().toString();
String userPassword = et_userPassword.getText().toString();
// 1. 創(chuàng)建一個(gè) Intent 對(duì)象,并傳入將要啟動(dòng)的目的 Activity
Intent intent = new Intent(SignUpActivity.this, SignUpSuccessActivity.class);
// 2. 往 Intent 的對(duì)象里放入需要傳遞的數(shù)據(jù)
intent.putExtra("userName", userName);
intent.putExtra("userPassword", userPassword);
// 3. 啟動(dòng)相應(yīng)的組件,將數(shù)據(jù)傳遞過(guò)去,并設(shè)置 requestCode
startActivityForResult(intent, 0);
}
// 在此方法中根據(jù) requestCode 和 resultCode 對(duì)對(duì)應(yīng)的返回?cái)?shù)據(jù)進(jìn)行處理
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 0 && resultCode == 0) {
// 將 Button 上的文字設(shè)置為返回的數(shù)據(jù)
btn_signUp.setText(data.getStringExtra("signUpSuccess"));
btn_signUp.setTextColor(Color.RED);
}
}
}
- SignUpSuccessActivity.java:
public class SignUpSuccessActivity extends AppCompatActivity {
private TextView tv_userName;
private TextView tv_userPassword;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup_success);
// 設(shè)置 title
setTitle("注冊(cè)成功");
initView();
display();
}
// 該方法用來(lái)顯示用戶的注冊(cè)信息
private void display() {
//1. 獲取啟動(dòng)本 Activity 的 Intent
intent = getIntent();
// 2. 從 Intent 中取出數(shù)據(jù),根據(jù)鍵取出相應(yīng)的值
// 注意,此鍵要與傳遞過(guò)來(lái)的鍵一致,否則會(huì)出現(xiàn) NullPointerException 異常
String userName = intent.getStringExtra("userName");
String userPassword = intent.getStringExtra("userPassword");
// 3. 顯示用戶的注冊(cè)信息
tv_userName.setText("您的用戶名為:" + userName);
tv_userPassword.setText("您的注冊(cè)密碼為:" + userPassword);
// 設(shè)置返回的數(shù)據(jù)
intent.putExtra("signUpSuccess", "注冊(cè)成功");
// 設(shè)置 resultCode 和返回的 Intent
setResult(0, intent);
}
// 該方法用來(lái)實(shí)例化布局中的控件
private void initView() {
tv_userName = (TextView) findViewById(R.id.tv_userName);
tv_userPassword = (TextView) findViewById(R.id.tv_userPassword);
}
}
- 效果演示:

填寫(xiě)信息并點(diǎn)擊提交注冊(cè)按鈕:


點(diǎn)擊返回鍵:

可以看到,按鈕上的文字即為返回的數(shù)據(jù)。
使用 Bundle 傳遞數(shù)據(jù)
除了 Intent,Bundle 也可以用來(lái)傳遞數(shù)據(jù),其用法跟 Intent 差不多。將上面的程序修改成如下 (只須修改 SignUpActivity.java 和 SignUpSuccessActivity.java):
- SignUpActivity.java:
public class SignUpActivity extends AppCompatActivity {
private EditText et_userName;
private EditText et_userPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
// 設(shè)置 title
setTitle("注冊(cè)界面");
initView();
}
// 該方法用于實(shí)例化布局中的控件
private void initView() {
et_userName = (EditText) findViewById(R.id.et_userName);
et_userPassword = (EditText) findViewById(R.id.et_userPassword);
}
public void signUp(View view) {
// 獲取 EditText 里的數(shù)據(jù)
String userName = et_userName.getText().toString();
String userPassword = et_userPassword.getText().toString();
// 1. 創(chuàng)建一個(gè) Intent 對(duì)象,并傳入將要啟動(dòng)的 Activity
Intent intent = new Intent(SignUpActivity.this, SignUpSuccessActivity.class);
// 2. 創(chuàng)建一個(gè) Bundle 對(duì)象
Bundle bundle = new Bundle();
// 3. 往 Bundle 的對(duì)象里放入需要傳遞的數(shù)據(jù)
bundle.putString("userName", userName);
bundle.putString("userPassword", userPassword);
// 4. 將 Bundle 對(duì)象放進(jìn) Intent 里
intent.putExtras(bundle);
// 5. 啟動(dòng)相應(yīng)的組件,并將數(shù)據(jù)傳遞過(guò)去
startActivity(intent);
}
}
- SignUpSuccessActivity.java:
public class SignUpSuccessActivity extends AppCompatActivity {
private TextView tv_userName;
private TextView tv_userPassword;
private Bundle bundle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup_success);
// 設(shè)置 title
setTitle("注冊(cè)成功");
initView();
display();
}
// 該方法用來(lái)顯示用戶的注冊(cè)信息
private void display() {
//1. 獲取啟動(dòng)本 Activity 的 Intent 里的 Bundle
bundle = getIntent().getExtras();
// 2. 從 Bundle 中取出數(shù)據(jù),根據(jù)鍵取出相應(yīng)的值
// 注意,此鍵要與傳遞過(guò)來(lái)的鍵一致,否則會(huì)出現(xiàn) NullPointerException 異常
String userName = bundle.getString("userName");
String userPassword = bundle.getString("userPassword");
// 3. 顯示用戶的注冊(cè)信息
tv_userName.setText("您的用戶名為:" + userName);
tv_userPassword.setText("您的注冊(cè)密碼為:" + userPassword);
}
// 該方法用來(lái)實(shí)例化布局中的控件
private void initView() {
tv_userName = (TextView) findViewById(R.id.tv_userName);
tv_userPassword = (TextView) findViewById(R.id.tv_userPassword);
}
}
從上面的代碼可以看出,使用 Bundle 來(lái)傳遞數(shù)據(jù)跟使用 Intent 來(lái)傳遞數(shù)據(jù)差不多。實(shí)際上還是用的 Intent 來(lái)傳遞數(shù)據(jù),只不過(guò) Intent 并不直接將數(shù)據(jù)傳遞過(guò)去,而是傳遞一個(gè) Bundle 對(duì)象,我們將要傳遞的數(shù)據(jù)封裝在一個(gè) Bundle 對(duì)象里,再使用 Intent 將 Bundle 對(duì)象傳遞過(guò)去。
- 效果演示:
效果跟上面的程序完全一樣。
2. 傳遞對(duì)象
當(dāng)要傳遞的數(shù)據(jù)較多時(shí),我們可以把數(shù)據(jù)封裝成一個(gè)對(duì)象,再把這個(gè)對(duì)象傳遞過(guò)去,條件是該對(duì)象必須實(shí)現(xiàn) Serializable 接口或 Parcelable 接口。
- 對(duì)象實(shí)現(xiàn) Serializable 接口
在使用內(nèi)存方面,Serializable 效率比 Parcelable 低,但它能把數(shù)據(jù)存儲(chǔ)在磁盤(pán)上。
a. XML 布局文件
信息提交頁(yè)面,activity_info.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓名:" />
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請(qǐng)輸入姓名" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="年齡:" />
<EditText
android:id="@+id/et_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請(qǐng)輸入年齡" />
</TableRow>
<Button
android:id="@+id/btn_summit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交"
android:onClick="summit"/>
</LinearLayout>
信息顯示頁(yè)面,activity_info_display.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_age"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
b. Java 代碼
信息提交頁(yè)面,InfoSummitActivity.java:
public class InfoSummitActivity extends AppCompatActivity {
private EditText et_name;
private EditText et_age;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_info);
// 設(shè)置 title
setTitle("提交信息");
initView();
}
// 該方法用于實(shí)例化布局中的控件
private void initView() {
et_name = (EditText) findViewById(R.id.et_name);
et_age = (EditText) findViewById(R.id.et_age);
}
// 該方法用于提交用戶信息,并跳轉(zhuǎn)用戶信息頁(yè)面
public void summit(View view) {
// 獲取 EditText 里的信息
String name = et_name.getText().toString();
int age = Integer.parseInt(et_age.getText().toString());
// 1. 創(chuàng)建一個(gè) Teacher 對(duì)象,并設(shè)置其屬性
Teacher teacher = new Teacher();
teacher.setName(name);
teacher.setAge(age);
// 2. 創(chuàng)建一個(gè) Intent 對(duì)象,指定要跳轉(zhuǎn)的目的組件
Intent intent = new Intent(InfoSummitActivity.this, InfoDisplayActivity.class);
// 3. 將要傳遞的對(duì)象放入 Intent 中
intent.putExtra("teacher", teacher);
// 4. 跳轉(zhuǎn)到對(duì)應(yīng)的組件
startActivity(intent);
}
}
信息顯示頁(yè)面,InfoDisplayActivity.java:
public class InfoDisplayActivity extends AppCompatActivity {
private TextView tv_name;
private TextView tv_age;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_info_display);
// 設(shè)置 title
setTitle("用戶信息");
initView();
display();
}
// 該方法用于顯示用戶的信息
private void display() {
// 1. 獲取啟動(dòng)本 Activity 的 Intent
intent = getIntent();
// 2. 創(chuàng)建一個(gè) Teacher 對(duì)象,用來(lái)接收從 Intent 里取出的數(shù)據(jù)
Teacher teacher = (Teacher) intent.getSerializableExtra("teacher");
// 3. 設(shè)置數(shù)據(jù)到對(duì)應(yīng)的控件上
tv_name.setText("您的姓名是:" + teacher.getName());
tv_age.setText("您的年齡為:" + teacher.getAge());
// 注意,由于 setText 只能接受 CharSequence 類(lèi)型的參數(shù),
// 而在這里我們的年齡是 int 類(lèi)型的,如果寫(xiě)成:
// tv_age.setText(teacher.getAge());
// 點(diǎn)擊按鈕時(shí)會(huì)出現(xiàn) Resources$NotFoundException,即資源未找到異常
// 解決辦法是加個(gè)空字符:tv_age.setText(teacher.getAge() + "");
}
// 該方法用于實(shí)例化布局中的控件
private void initView() {
tv_name = (TextView) findViewById(R.id.tv_name);
tv_age = (TextView) findViewById(R.id.tv_age);
}
}
c. 效果演示:

輸入信息,并點(diǎn)擊提交按鈕:


- 對(duì)象實(shí)現(xiàn) Parcelable 接口
- 在使用內(nèi)存方面,Parcelable 效率比 Serializable 高,但它不能將數(shù)據(jù)存儲(chǔ)在磁盤(pán)上。
- 實(shí)現(xiàn) Parcelable 接口必須重寫(xiě) writeToParcel() 方法和 describeContents() 方法,并實(shí)例化靜態(tài)內(nèi)部對(duì)象 CREATOR 實(shí)現(xiàn) Creator 接口。詳情請(qǐng)看這篇文章 Android中Parcelable接口用法
a. XML 布局文件
信息提交頁(yè)面,activity_info.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓名:" />
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請(qǐng)輸入姓名" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="學(xué)號(hào):" />
<EditText
android:id="@+id/et_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請(qǐng)輸入學(xué)號(hào)" />
</TableRow>
<Button
android:id="@+id/btn_summit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交"
android:onClick="summit"/>
</LinearLayout>
信息顯示頁(yè)面,activity_info_display.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_id"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
b. Java 代碼
新建一個(gè) Student 類(lèi),該類(lèi)實(shí)現(xiàn)了 Parcelable 接口:
public class Student implements Parcelable {
private String name;
private int id;
public Student() {
}
public Student(Parcel source) {
name = source.readString();
id = source.readInt();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
// 此方法為內(nèi)容描述,默認(rèn)即可
@Override
public int describeContents() {
return 0;
}
// 此方法用來(lái)寫(xiě)入數(shù)據(jù)
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
dest.writeInt(this.id);
}
// 實(shí)例化 CREATOR 對(duì)象,實(shí)現(xiàn) Creator 接口
public static final Creator<Student> CREATOR = new Creator<Student>() {
// 此方法用來(lái)讀取傳遞過(guò)來(lái)的數(shù)據(jù),注意讀取的順序要與寫(xiě)入的順序一致
@Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
// 此方法用來(lái)供外部類(lèi)反序列化本類(lèi)數(shù)組使用
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
信息提交頁(yè)面,InfoSummitActivity.java:
public class InfoSummitActivity extends AppCompatActivity {
private EditText et_name;
private EditText et_id;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_info);
// 設(shè)置 title
setTitle("提交信息");
initView();
}
// 該方法用于實(shí)例化布局中的控件
private void initView() {
et_name = (EditText) findViewById(R.id.et_name);
et_id = (EditText) findViewById(R.id.et_id);
}
// 該方法用于提交用戶信息,并跳轉(zhuǎn)用戶信息頁(yè)面
public void summit(View view) {
// 獲取 EditText 里的信息
String name = et_name.getText().toString();
int id = Integer.parseInt(et_id.getText().toString());
// 1. 創(chuàng)建一個(gè) Student 對(duì)象,并設(shè)置其屬性
Student student = new Student();
student.setName(name);
student.setId(id);
// 2. 創(chuàng)建一個(gè) Intent 對(duì)象,指定要跳轉(zhuǎn)的目的組件
Intent intent = new Intent(InfoSummitActivity.this, InfoDisplayActivity.class);
// 3. 將要傳遞的對(duì)象放入 Intent 中
intent.putExtra("student", student);
// 4. 跳轉(zhuǎn)到對(duì)應(yīng)的組件
startActivity(intent);
}
}
信息顯示頁(yè)面,InfoDisplayActivity.java:
public class InfoDisplayActivity extends AppCompatActivity {
private TextView tv_name;
private TextView tv_id;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_info_display);
// 設(shè)置 title
setTitle("用戶信息");
initView();
display();
}
// 該方法用于顯示用戶的信息
private void display() {
// 1. 獲取啟動(dòng)本 Activity 的 Intent
intent = getIntent();
// 2. 創(chuàng)建一個(gè) Student 對(duì)象,用來(lái)接收從 Intent 里取出的數(shù)據(jù)
Student student = intent.getParcelableExtra("student");
// 3. 設(shè)置數(shù)據(jù)到對(duì)應(yīng)的控件上
tv_name.setText("您的姓名是:" + student.getName());
tv_id.setText("您的學(xué)號(hào)是:" + student.getId());
// 注意,由于 setText 只能接受 CharSequence 類(lèi)型的參數(shù),
// 而在這里我們的年齡是 int 類(lèi)型的,如果寫(xiě)成:
// tv_id.setText(student.getId());
// 點(diǎn)擊按鈕時(shí)會(huì)出現(xiàn) Resources$NotFoundException,即資源未找到異常
// 解決辦法是加個(gè)空字符:tv_id.setText(student.getId() + "");
}
// 該方法用于實(shí)例化布局中的控件
private void initView() {
tv_name = (TextView) findViewById(R.id.tv_name);
tv_id = (TextView) findViewById(R.id.tv_id);
}
}
c. 效果演示:

填寫(xiě)信息,并點(diǎn)擊提交按鈕:


總結(jié):使用 Intent 在 Activity 之間傳遞數(shù)據(jù)
- 在傳遞數(shù)據(jù)的地方創(chuàng)建一個(gè) Intent 對(duì)象;
Intent intent = new Intent();
- 對(duì) Intent 對(duì)象進(jìn)行設(shè)置,可以傳入簡(jiǎn)單的數(shù)據(jù)、對(duì)象 (包括 Bundle 對(duì)象),注意傳入的參數(shù)鍵值對(duì)形式;
- intent.putExtra("key", value);
- Person person = new Person(); intent.putExtra("person", person);
- Bundle bundle = new Bundle(); bundle.putXxx("key", value); intent.putExtra("bundle", bundle); // Xxx 為具體數(shù)據(jù)類(lèi)型
- 在接收數(shù)據(jù)的地方創(chuàng)建一個(gè) Intent 對(duì)象;
Intent intent = new Intent();
- 獲取啟動(dòng)本 Activity 的 Intent;
intent = getIntent();
- 從 Intent 中取出數(shù)據(jù),根據(jù)鍵取出相應(yīng)的值,注意,此鍵要與傳遞過(guò)來(lái)的鍵一致,否則會(huì)出現(xiàn) NullPointerException 異常;根據(jù)傳遞過(guò)來(lái)的值的類(lèi)型,用對(duì)應(yīng)的數(shù)據(jù)類(lèi)型去接收。
- String string = intent.getStringExtra("string");
- Teacher teacher = (Teacher) intent.getSerializableExtra("teacher");
- Student student = intent.getParcelableExtra("student");
參考資料: