Intent 是 Android 非常常用的一個(gè)用于組件間互相通信的信息對(duì)象,常用于啟動(dòng)組件和傳遞數(shù)據(jù),大部分的程序里都有著他的身影。Intent 的用法比較簡(jiǎn)單,看看示例代碼自然而然就用了起來,相信很多人和我之前一樣也是沒有仔細(xì)的去了解過。本文總結(jié)了一下 Intent 的結(jié)構(gòu)和用法,除了一般的用法外,像隱式 Intent 的匹配規(guī)則之類可能很多人都比較一知半解的內(nèi)容也會(huì)進(jìn)行深入。
Intent 的包含信息與構(gòu)造
Intent 作為一個(gè)負(fù)責(zé)組件間傳遞消息的信息對(duì)象,最重要的就是其包含的信息。實(shí)際上無論是顯式還是隱式,Intent 發(fā)出的時(shí)候,系統(tǒng)對(duì)應(yīng)的行為正是由 Intent 所包含信息的組合決定。一個(gè) Intent 所包含的信息如下圖:
Intent 的各部分信息均為可選值,但是在使用 Intent 的時(shí)候,會(huì)根據(jù) Intent 設(shè)定的信息組合來決定對(duì)應(yīng)行為。先來看看 Intent 的構(gòu)造方法和一些常用設(shè)定信息的方法
Intent 常用構(gòu)造方法:
| 方法 | 描述 |
|::|:-----|
|Intent() | 構(gòu)造一個(gè)空 Intent |
| Intent(String action)| 構(gòu)造一個(gè)指定 action 的 Intent |
| Intent(String action,Uri uri)| 構(gòu)造一個(gè)指定 action 和 uri(相當(dāng)于同時(shí)設(shè)定了 data)的 Intent|
| Intent(Context packageContext,Class<?> cls)| 構(gòu)造一個(gè)指定目標(biāo)組件的 Intent,顯式 Intent 的主要構(gòu)造方法 |
常用的設(shè)定信息方法:
| 方法 | 描述 |
|::|:-----|
|setAction(String action)|指定 action|
|setClass(Context packageContext, Class<?> cls)|指定目標(biāo)組件類名|
|setData(Uri data)|設(shè)置 Data 的 uri|
|setType(String type)|設(shè)置 Data 的 MIME 類型|
|setDataAndType(Uri data, String type)|同時(shí)設(shè)置 Data 的 uri 與 MIME 類型|
|addCategory(String category)|添加一項(xiàng) Category,Intent 可有多個(gè) Category|
|addFlags(int flags)|設(shè)置 Flag,決定目標(biāo)組件的啟動(dòng)方式|
|putExtra(String name, 基本類型和序列化類 value)|放入附加數(shù)據(jù),參 2 可以是各種基本類型,及序列化后的自定義類|
|putExtras(Bundle extras)|把封裝了數(shù)據(jù)信息的 Bundle 對(duì)象放入 Intent|
*若要同時(shí)設(shè)置 URI 和 MIME 類型,請(qǐng)勿調(diào)用 setData() 和 setType(),因?yàn)樗鼈儠?huì)互相抵消彼此的值。請(qǐng)始終使用 setDataAndType() 同時(shí)設(shè)置 URI 和 MIME 類型。
目標(biāo)組件名稱
顯式 Intent 的必要信息,指定后 Intent 僅傳給指定的組件(也就是所謂顯性 Intent),否則系統(tǒng)會(huì)根據(jù)其他信息篩選出可以響應(yīng) Intent 的所有組件(即隱性 Intent)。可以使用 setComponent()、setClass()、setClassName() 或 Intent 構(gòu)造函數(shù)設(shè)置組件名稱。
** 由于安全性原因,在5.0后的系統(tǒng),啟動(dòng) Service 時(shí),應(yīng)始終指定組件名稱,否則會(huì)報(bào)錯(cuò)。**
Action
指 Intent 發(fā)向的組件的主要?jiǎng)幼鳎热纾簣D片應(yīng)用中主要?jiǎng)幼鳛椴榭磮D片的組件、地圖應(yīng)用中主要?jiǎng)幼鳛椴榭吹刂返慕M件。另外,對(duì)于廣播(Broadcast)組件而言,Intent 的 action 則是指廣播具體的值。當(dāng) Broadcast Receiver 接收到該值時(shí)代表了某事件已經(jīng)發(fā)生。
通常使用的主要是 Android 系統(tǒng)內(nèi)置 action,這些 action 實(shí)際上是保存在 Intent 類中的靜態(tài)常量,系統(tǒng)的默認(rèn)組件(如:默認(rèn)瀏覽器、圖片瀏覽器、撥號(hào)頁面等)都可以響應(yīng)相應(yīng)的 action。下面給出幾個(gè)比較常見內(nèi)置 action。
ACTION_VIEW
向用戶展示某信息,比如使用瀏覽器打開網(wǎng)址,用圖片應(yīng)用顯示圖片等
ACTION_SEND
用于發(fā)送數(shù)據(jù),比如電子郵件應(yīng)用或者一些社交應(yīng)用。
ACTION_DIAL
顯示帶撥號(hào)盤的頁面,讓用戶可以進(jìn)行撥號(hào)動(dòng)作。
有關(guān)更多定義通用操作的常量,請(qǐng)參閱 Intent類參考文檔。
除了 Android 內(nèi)置的 action 之外,也可以自定義action, 供 Intent 在自己的應(yīng)用內(nèi)使用(或者供其他應(yīng)用在自己的應(yīng)用中調(diào)用組件)。如果定義自己的操作,請(qǐng)確保將應(yīng)用的軟件包名稱作為前綴。 例如:
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
Data
包含了 URI 對(duì)象和 memitype 兩個(gè)部分,分別是待操作數(shù)據(jù)的引用 uri,以及待操作數(shù)據(jù)的數(shù)據(jù)類型。兩部分均為可選,但是要注意同時(shí)設(shè)置時(shí)應(yīng)該使用 setDataAndType()
方法,防止互相抵消。
Data 內(nèi)容一般由 action 決定,比如 action 為 ACTION_VIEW,那么 Data 就可以是一個(gè)網(wǎng)址,也可以是圖片之類的數(shù)據(jù) uri。
同時(shí)指定 Uri 和 MIME 類型有助于 Android 系統(tǒng)找到接收 Intent 的最佳組件,例如可以響應(yīng) ACTION_VIEW 的組件可能有非常多,瀏覽器、播放器、圖片應(yīng)用等等。此時(shí)設(shè)置mimeType
為"image/jpeg"
或者video/mp4
,則系統(tǒng)可以篩選出更合適的響應(yīng)組件。
Category
目標(biāo)組件的類型信息字符串,一個(gè) Intent 可以添加多個(gè) Category 。以下是比較常見的 Category:
CATEGORY_BROWSABLE
目標(biāo) Activity 允許本身通過網(wǎng)絡(luò)瀏覽器啟動(dòng),以顯示鏈接引用的數(shù)據(jù),如圖像或電子郵件。
CATEGORY_LAUNCHER
該 Activity 是任務(wù)的初始 Activity,在系統(tǒng)的應(yīng)用啟動(dòng)器中列出。
需要注意的是大部分 Intent 雖然不需要設(shè)置 Category,但是在調(diào)用使用 Intent 的方法(如starActivity()
等)的時(shí)候,會(huì)默認(rèn)為該 Intent 添加 CATEGORY_DEFAULT,相應(yīng)目標(biāo)組件的Intent過濾器應(yīng)該添加該類別,具體會(huì)在下文 2、Intent的用法 中詳述。
以上 4 種(組件類名、Action、Data、Category)是會(huì)影響系統(tǒng)對(duì) Intent 的解析從而決定最終啟動(dòng)那個(gè)組件的信息,以下兩種(Extra、Flag)屬于附加的信息,不影響系統(tǒng)解析啟動(dòng)那個(gè)組件
Extra
Intent 攜帶附加數(shù)據(jù),也是組件間互相傳遞信息比較常見的做法。使用各種 putExtra()
方法添加 extra 數(shù)據(jù),每種方法均接受兩個(gè)參數(shù):鍵名和值。還可以創(chuàng)建一個(gè)包含所有 extra 數(shù)據(jù)的 Bundle 對(duì)象,然后使用 putExtras()
將 Bundle 插入 Intent 中。
具體用法在下文 3、數(shù)據(jù)傳送 中詳述。
Flag
指示 Android 系統(tǒng)如何啟動(dòng) Activity,例如,Activity 應(yīng)屬于哪個(gè)任務(wù),以及啟動(dòng)之后如何處理(例如,它是否屬于最近的 Activity 列表)。
Intent 構(gòu)造示例:
Intent intent = new Intent(this,TagerActivity.class);//顯式 Intent 構(gòu)造示例
//隱式Intent構(gòu)造示例
Intent intent=new Intent(Intent.ACTION_VIEW);//設(shè)定 action 為展示內(nèi)容
intent.setData(Uri.parse("http://www.baidu.com"));//設(shè)置 data 的 uri 為一個(gè)網(wǎng)址
intent.addCategory(Intent.CATEGORY_LAUNCHER);//目標(biāo)組件為某個(gè)應(yīng)用的首頁面
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);//目標(biāo) Activity 的啟動(dòng)方式為 single top
intent.putExtra("extra_my","Tom");//附加 String 數(shù)據(jù)
Intent的用法
Intent 主要分為顯式 Intent 和隱式 Intent,根據(jù)顯隱用法不同。
常用發(fā)送 Intent 啟動(dòng)組件方法:
| 方法 | 描述 |
|::|:-----|
|startActivity() | 啟動(dòng) Activity|
|startActivityForResult()| 啟動(dòng) Activity,該 Activity 銷毀后會(huì)回調(diào)到上個(gè)活動(dòng)的 onActivityResult() 方法 |
| bindService()| 啟動(dòng) Service,5.0后只能接收顯性 Intent 作為參數(shù)|
|sendBroadcast()| 發(fā)送標(biāo)準(zhǔn)廣播 |
|sendOrderedBroadcast()| 發(fā)送有序廣播 |
顯式
顯式 Intent 通常應(yīng)用在自己的程序中,啟動(dòng)特定組件。用法比較簡(jiǎn)單,就是構(gòu)造一個(gè)帶有目標(biāo)組件名的 Intent,作為參數(shù)傳入上述方法即可,調(diào)用方法后會(huì)直接啟動(dòng)相應(yīng)組件。
值得注意的就是在5.0之后的系統(tǒng), Service 只能通過顯式 Intent 啟動(dòng)。
隱式
隱式 Intent 允許啟動(dòng)其他應(yīng)用中的組件,在調(diào)用發(fā)送 Intent 的方法后,該 Intent 會(huì)交由 Android 系統(tǒng)進(jìn)行匹配,(匹配根據(jù)信息是 action、data、category 這3項(xiàng),即本文第一張圖片 Intent 包含信息中標(biāo)藍(lán)色部分)篩選出整個(gè)設(shè)備可響應(yīng)該 Intent 的組件。下圖官方文檔對(duì)隱式 Intent 如何傳遞啟動(dòng)其他應(yīng)用組件的圖解:
Intent過濾器
Intent 過濾器是 manifests 里組件的子標(biāo)簽<intent-filter>
,一個(gè)控件可以聲明一個(gè)或者**多個(gè) **Intent 過濾器,只要其中一個(gè)通過匹配,該組件就可以相應(yīng)相應(yīng) Intent。先來看一個(gè)官方給出的 Intent 過濾器示例:
<activity android:name="MainActivity">
<!-- 應(yīng)用的首頁面,會(huì)顯示在啟動(dòng)器中 -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="ShareActivity">
<!-- 該活動(dòng)可以處理 SEND這個(gè) aciton,且處理數(shù)據(jù)類型為無格式文本 -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<!--需要響應(yīng)隱式Intent的活動(dòng)必須添加 android.intent.category.DEFAULT這個(gè)分類,因?yàn)閟tarActivity()方法會(huì)默認(rèn)為Intent添加-->
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<!-- 此為同一個(gè) Activity 的第二個(gè)過濾器 該活動(dòng)可以處理 "SEND" 和 "SEND_MULTIPLE"兩種 aciton 處理數(shù)據(jù)類型為多媒體數(shù)據(jù)(包括圖片、視頻和全景照片) -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/vnd.google.panorama360+jpg"/>
<data android:mimeType="image/*"/>
<data android:mimeType="video/*"/>
</intent-filter>
</activity>
這里值得注意的幾個(gè)點(diǎn):
- 1 Intent 只能有1個(gè) action,而 Intent 過濾器可有多個(gè) action
- 2 需要響應(yīng)隱式 Intent 的 Activity 的 Intent 過濾器中必須添加 android.intent.category.DEFAULT這個(gè)分類
- 3 data 在構(gòu)造時(shí)傳入的是 Uri 對(duì)象以及 mimeType 字符串,mimeType 的對(duì)應(yīng)關(guān)系比較直觀不詳述,Uri 對(duì)象會(huì)被分為 4 個(gè)部分
<scheme>://<host>:<port>/<path>
(<協(xié)議>://<主機(jī)名>:<端口>/<路徑>),在 Intent 過濾器中的寫法如下:
<intent-filter>
<data
android:scheme="content" android:host="com.example.project"
android:port="200" android:path="/folder/subfolder/etc"/>
</intent-filter>
對(duì)應(yīng)的Uri對(duì)象:
Uri uri=Uri.parse("content://com.example.project:200/folder/subfolder/etc");
4 path 和 mimeType 允許使用*通配符,實(shí)現(xiàn)部分匹配。
5 對(duì)于所有 Activity,必須在清單文件中聲明 Intent 過濾器。
但是,廣播接收器的過濾器可以通過調(diào)用 registerReceiver() 動(dòng)態(tài)注冊(cè)。 且可以使用 unregisterReceiver() 注銷該接收器。這樣一來,應(yīng)用便可僅在應(yīng)用運(yùn)行時(shí)的某一指定時(shí)間段內(nèi)偵聽特定的廣播。
匹配規(guī)則
隱式 Intent 會(huì)與所有設(shè)備所有應(yīng)用組件的 Intent 過濾器進(jìn)行比對(duì)。
一個(gè)組件可以有多個(gè) Intent 過濾器,某個(gè) Intent 只需與其中任何一個(gè)匹配即可啟動(dòng)組件。
系統(tǒng)會(huì)根據(jù) Intent 與 Intent 過濾器的 action、data、category 進(jìn)行三次比對(duì)(測(cè)試),要全部通過才能匹配。
action 的匹配規(guī)則:
A、Intent 只能包含一項(xiàng) action,而 Intent 過濾器可以包含多項(xiàng) action,只要 Intent 的 action 可以在 Intent 過濾器中找到對(duì)應(yīng)項(xiàng)即可通過測(cè)試。
B、當(dāng) Intent 過濾器未聲明任何 action 時(shí),任何 Intent 都不能通過匹配。
C、當(dāng) Intent 未指定 Action 時(shí),無法通過匹配。category 的匹配規(guī)則:
A、Intent 可以包含多項(xiàng) category,Intent 過濾器也可以包含多項(xiàng) category。Intent 中的每項(xiàng) category 必須在Intent過濾器中都有對(duì)應(yīng)項(xiàng),才能通過匹配。
B、當(dāng)目標(biāo)組件為 Activity 時(shí),如需相應(yīng)隱式 Intent,必須添加 "android.intent.category.DEFAULT" 到 Intent 過濾器中。因?yàn)閱?dòng)Activity的方法都會(huì)默認(rèn)為Intent添加該 category。
C、目標(biāo)組件為廣播時(shí),Intent 和 Intent 過濾器都不設(shè)置 category,可通過匹配。data的匹配規(guī)則:
和上面兩個(gè)元素不同,data 具有子元素,其構(gòu)成如下圖:
在 Intent 中傳入的 Uri 對(duì)象會(huì)被解析成<scheme>://<host>:<port>/<path>
(<協(xié)議>://<主機(jī)名>:<端口>/<路徑>)4 個(gè)部分進(jìn)行匹配測(cè)試。4 項(xiàng)均為可選,但是存在線性依賴關(guān)系:
如果未指定 scheme,則會(huì)忽略 host;
如果未指定 host,則會(huì)忽略 port;
如果未指定 scheme 和 host,則會(huì)忽略 path。
data 的匹配規(guī)則主要有以下幾點(diǎn):
A、將 Intent 中的 URI 與過濾器中的 URI 規(guī)范進(jìn)行比較時(shí),它僅與過濾器中包含的部分 URI 進(jìn)行比較。 例如:
- 如果過濾器僅指定 scheme,則具有該 scheme 的所有 URI 均與該過濾器匹配。
- 如果過濾器指定 scheme 和 host,但未指定 path,則具有相同 scheme 和 host 的所有 URI 都會(huì)通過過濾器,無論其 path 如何均是如此。
- 如果過濾器指定 scheme、host和path,則僅具有相同 scheme、host 和 path 的 URI 才會(huì)通過過濾器。
- path 部分可以使用*通配符,僅需部分匹配路徑名即可。
B、mimeType 可以部分使用通配符,如:image/*
(表示匹配所有格式圖像數(shù)據(jù)),也可以全部使用*/*
表示匹配所有類型數(shù)據(jù)。
C、當(dāng)Intent同時(shí)不指定 uri 與 mimeType 時(shí),只有同樣未聲明 uri 與 mimeType 的 Intent 過濾器可以通過匹配。
D、當(dāng) Intent 只含有 uri 時(shí),只有聲明 uri 相互匹配,且未聲明 mimeType 的 Intent 過濾器可以通過匹配。
E、當(dāng) Intent 只含有 mimeType 時(shí),只有 mimeType 相互匹配,且未聲明 uri 的 Intent 過濾器可以通過匹配。
F、當(dāng) Intent 同時(shí)含有 uri 和 mimeType 時(shí),只有兩部分均匹配的 Intent 過濾器可以通過匹配。
G、Intent過濾器只聲明mimeType時(shí),默認(rèn)支持scheme為content: 和 file: 的uri。
H、當(dāng) Intent 傳入的 uri 為 content: URI 時(shí),表明數(shù)據(jù)位于設(shè)備中,且由 ContentProvider 控制,此時(shí)即使不設(shè)置 mimeType,mimeType 也對(duì)系統(tǒng)可見。
非空判斷
當(dāng)隱式 Intent 發(fā)出而找不到匹配 Activity 時(shí),調(diào)用將會(huì)失敗,且應(yīng)用會(huì)崩潰。要驗(yàn)證是否存在會(huì)接收 Intent 的 Activity ,可以對(duì) Intent 對(duì)象調(diào)用 resolveActivity()。如果結(jié)果為非空,則至少有一個(gè)應(yīng)用能夠處理該 Intent,且可以安全調(diào)用 startActivity()。 如果結(jié)果為空,則不應(yīng)使用該 Intent,應(yīng)停用發(fā)出該 Intent 的功能。
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
// 判斷是否存在能夠匹配該 Intent 的 Activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
強(qiáng)制使用選擇器
當(dāng)存在多個(gè) Activity 響應(yīng) Intent 時(shí),系統(tǒng)會(huì)彈出默認(rèn)選擇器,供用戶選擇啟動(dòng) Activity,且用戶可以選擇為該操作設(shè)定默認(rèn)選項(xiàng)。
根據(jù)應(yīng)用場(chǎng)景,有一些 Intent 可能并不適合存在默認(rèn)選項(xiàng)。例如,當(dāng)應(yīng)用使用 ACTION_SEND 操作執(zhí)行“共享”時(shí),用戶根據(jù)目前的狀況可能需要使用另一不同的應(yīng)用。此時(shí)可以強(qiáng)制顯示選擇器(顯式的調(diào)用選擇器),選擇器對(duì)話框每次都會(huì)要求用戶選擇用于操作的應(yīng)用(用戶無法為該操作選擇默認(rèn)應(yīng)用)。
具體使用createChooser()方法,接收兩個(gè)參數(shù),第一個(gè)是包含信息的 Intent,第二個(gè)是選擇器的標(biāo)題。
Intent viewIntent=new Intent();
viewIntent.setAction(Intent.ACTION_VIEW);
//createChooser()方法,顯式調(diào)用選擇器,用戶將無法設(shè)定默認(rèn)選項(xiàng)
Intent intent=Intent.createChooser(viewIntent,"應(yīng)用選擇器");
//判斷該Intent是否存在可響應(yīng)Activity,用未使用createChooser()方法的原Intent進(jìn)行判斷
if (viewIntent.resolveActivity(getPackageManager())==null) return;
startActivity(intent);
數(shù)據(jù)傳送
Intent 作為組件間的信息對(duì)象,另一個(gè)主要作用就是數(shù)據(jù)的傳送。
Intent傳送數(shù)據(jù)是以鍵值對(duì)的形式,主要通過putExtra()
方法,該方法接收兩個(gè)參數(shù),第一個(gè)是數(shù)據(jù)的鍵,
第二個(gè)是數(shù)據(jù)的值。第二個(gè)參數(shù)的取值范圍包括8種基本數(shù)據(jù)類型和 String、CharSequence,以及他們的數(shù)組,另外還可以是 Parcelable(包含數(shù)組)、Serializable,以及包含數(shù)據(jù)的 Bundle 對(duì)象。
基本類型的傳出與回傳
在目標(biāo)組件中取出 Intent 的方法根據(jù)數(shù)據(jù)類型有非常多,這里不一一列舉,只給出一般格式。
方法 | 描述 | 默認(rèn)取值 |
---|---|---|
getXxxExtra(String name,基本數(shù)據(jù)類型 默認(rèn)值) | Xxx 為基本數(shù)據(jù)類型 | Extra 中無對(duì)應(yīng)鍵名時(shí),取方法參數(shù) 2 |
getXxxExtra(String name) | Xxx為Srting等引用類型 | Extra 中無對(duì)應(yīng)鍵名時(shí),取值 null |
getBundleExtra(String name) | 取出Bundle對(duì)象的方法 | Extra 中無對(duì)應(yīng)鍵名時(shí),取值 null |
getXxxArrayExtra() | 取出Xxx類型對(duì)應(yīng)數(shù)組方法 | Extra 中無對(duì)應(yīng)鍵名時(shí),取值 null |
ps:方法使用駝峰法,單詞間首字母大寫。
//添加 Extra 示例
Intent intent = new Intent(this,TagerActivity.class);
intent.putExtra("extra_int",1000);
int[] ints={1,2,3};
intent.putExtra("extra_int_array",ints);
intent.putExtra("extra_string","teger Activity");
startActivity(intent);
------------------------------------------
//對(duì)應(yīng)取出數(shù)據(jù)示例
Intent intent=getIntent();
int i=intent.getIntExtra("extra_int",0);
int[] ints=intent.getIntArrayExtra("extra_int_array");
String a=intent.getStringExtra("extra_string");
- 數(shù)據(jù)回傳
把數(shù)據(jù)傳回上個(gè)活動(dòng)也是 Intent 比較常用的方法之一。
實(shí)現(xiàn)的方式是在啟動(dòng)活動(dòng)時(shí)使用startActivityForResult(Intent intent,int requestCode)
代替startActivity(Intent intent)
,當(dāng)被啟動(dòng)活動(dòng)銷毀時(shí),就會(huì)攜帶一個(gè) Intent 回調(diào)到調(diào)用startActivityForResult()
方法的Activity的startActivityForResult()
方法。關(guān)于 Intent 添加 Extra,和數(shù)據(jù)的取出和普通的用法并沒有什么區(qū)別。
基本的步驟是:
A、調(diào)用startActivityForResult()
方法啟動(dòng)新 Activity,該方法有兩個(gè)參數(shù),參 1 為 Intent,參 2 為 int 類型的唯一請(qǐng)求碼,用于判斷數(shù)據(jù)來源。
B、在新 Activity 中調(diào)用setResult()
方法把攜帶希望回傳數(shù)據(jù)的 Intent 作為參數(shù)傳入。
C、重寫原 Activity 的onActivityResult()
方法。該方法攜帶 3 個(gè)參數(shù),參 1 為啟動(dòng) Activity 的請(qǐng)求碼 requestCode,參 2 為表示處理結(jié)果是否成功的 resultCode,參 3 為攜帶數(shù)據(jù)的 Intent。
重寫的主要邏輯是:先通過 requestCode 判斷數(shù)據(jù)來源(根據(jù)場(chǎng)景,原 Activity 可能啟動(dòng)不同新 Activity);然后通過 resultCode 判斷處理結(jié)果是否成功;最后取出 Intent 中數(shù)據(jù)進(jìn)行處理即可。
//原 Activity 中啟動(dòng)新 Activity 并請(qǐng)求返回?cái)?shù)據(jù)
Intent intent = new Intent(this,TagerActivity.class);
startActivityForResult(intent,1);
------------------------------------
//新 Activity 中設(shè)定返回 Intent 并銷毀,銷毀后會(huì)回調(diào)到原 Activity 的 onActivityResult()方法
Intent intent=new Intent();
intent.putExtra("extra_boolean",true);
setResult(RESULT_OK,intent);
finish();
------------------------------------
//原 Activity 中重寫 onActivityResult() 方法
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 1:
if (resultCode==RESULT_OK){
boolean b=data.getBooleanExtra("extra_boolean",false);
}
break;
default:
}
}
自定義類型序列化傳送
使用 Intent 來傳遞自定義對(duì)象主要有兩種實(shí)現(xiàn)方式:Serializable 和 Parcelable。
Serializable 是序列化的意思,是指將一個(gè)對(duì)象轉(zhuǎn)換成可存儲(chǔ)或可傳輸?shù)臓顟B(tài)。序列化后的對(duì)象可以在網(wǎng)絡(luò)上進(jìn)行傳輸,也可以存儲(chǔ)到本地。
Parcelable 也可以實(shí)現(xiàn)相同效果,其實(shí)現(xiàn)原理是將一個(gè)完整的對(duì)象進(jìn)行分解,而分解后的每一部分都是 Intent 所支持的數(shù)據(jù)類型,這樣也就實(shí)現(xiàn)傳遞對(duì)象的功能了。
兩種方式對(duì)比下 Serializable 比 Parcelable 效率偏低,Parcelable 實(shí)現(xiàn)雖然相對(duì)復(fù)雜,但是在 parceler之類的第三方庫支持下也變得非常簡(jiǎn)單,所以通常情況比較推薦用 Parcelable 的方式實(shí)現(xiàn) Intent 傳遞對(duì)象。
自定義類實(shí)現(xiàn) Serializable 示例:
public class User implements Serializable {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
非常簡(jiǎn)單,只要讓自定義類實(shí)現(xiàn) Serializable 接口即可。
Parcelable 方式比 Serializable 多出幾個(gè)步驟:1、重寫 describeContents() 返回 0 即可;2、重寫writeToParcel() 寫出字段;3、提供一個(gè) CREATOR 常量。
自定義類實(shí)現(xiàn)Parcelable示例:
public class User implements Parcelable {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//步驟1:重寫 describeContents() 返回0即可
@Override public int describeContents() {
return 0;
}
//步驟2:重寫 writeToParcel() 寫出字段
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(id);
}
//步驟3:提供一個(gè) CREATOR 常量
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
@Override public User createFromParcel(Parcel source) {
User user = new User();
user.id = source.readInt();
user.name = source.readString();
return user;
}
@Override public User[] newArray(int size) {
return new User[size];
}
};
}
添加 Extra 與取出示例:
User user=new User();
user.setId(1);
user.setName("Tom");
Intent intent = new Intent(this,TagerActivity.class);
intent.putExtra("extra_user_data",user);
startActivity(intent);
------------------------------------------
Intent intent=getIntent();
//如果放入自定義類使用了 Serializable 方式,則改用 getSerializableExtra() 方法 ,另外需要取出數(shù)據(jù)需要轉(zhuǎn)型
User user=(User)intent.getParcelableExtra("extra_user_data");
和基本類型的放入取出基本相同,只需要注意轉(zhuǎn)型即可。
本文主要參考自: https://developer.android.com/guide/components/intents-filters.html