一個(gè)應(yīng)用中總會(huì)存在多個(gè)活動(dòng)影所,通過這些活動(dòng)的相互跳轉(zhuǎn)蹦肴,數(shù)據(jù)傳遞,邏輯處理猴娩,便可完成一個(gè)應(yīng)用的功能。在各個(gè)活動(dòng)的跳轉(zhuǎn)時(shí)裂七,會(huì)通過Intent(意圖),Intent使Activity跳轉(zhuǎn)大致可分為顯示意圖和隱式意圖.
1.使用顯式 Intent
Intent有多個(gè)構(gòu)造函數(shù)的重載仓坞,其中一個(gè)是Intent(Context packageContext ,Class<?>cls)无埃。這個(gè)構(gòu)造函數(shù)接收兩個(gè)參數(shù)徙瓶,第一個(gè)參數(shù)Context是要求提供一個(gè)啟動(dòng)活動(dòng)的上下文,第二個(gè)參數(shù)需要指定一個(gè)目標(biāo)活動(dòng)侦镇。如下代碼:
? ? ? Intent intent = new Intent(MainActivity.this,SecondActivity.class);
? ? ? ?startActivity(Intent);
活動(dòng)本就是一個(gè)Context對(duì)象织阅,所以第一個(gè)參數(shù)傳入this,第二個(gè)參數(shù)傳入SecondActivity為目標(biāo)活動(dòng)闹炉,然后通過startActivity()方法執(zhí)行這個(gè)Intent。這種傳入啟動(dòng)活動(dòng)和目標(biāo)活動(dòng)的方式稱為顯示Intent羡棵,不要忘記在AndroidManifest.xml文件中添加Activity聲明嗅钻。
2.使用隱式 Intent
相比較與顯示养篓,隱式Intent則含蓄了很多,它并沒有明確指出我們想要啟動(dòng)哪個(gè)活動(dòng)剔应,而是通過指定一系列更為抽象的action和category等信息语御,然后由系統(tǒng)去分析這個(gè)Intent,并幫我們找到合適的活動(dòng)去啟動(dòng)纤控。
什么叫做合適的活動(dòng)呢碉纺,簡單來說就是可以響應(yīng)我們這個(gè)隱式Intent的活動(dòng),就目前來說耿导,SecondActivity可以響應(yīng)什么樣的隱式Intent呢态贤,其實(shí)它現(xiàn)在還什么都響應(yīng)不了悠汽。需要我們手動(dòng)的去設(shè)置。之前提到過要在配置文件中聲明我們的活動(dòng)茬高,在活動(dòng)的標(biāo)簽下配置<intent-filter>的內(nèi)容假抄,從字面理解標(biāo)簽的意思是<意圖-篩選>丽猬。
? ?<activity ?android:name=".SecondActivity">
? ? ? ?<intent-filter>
? ? ? ? ? ? ?<action name="com.hm.intenttestdemo.ACTION.START"/>
? ? ? ? ? ? ? <category name="android.intent.category.DEFAULT"/>
? ? ? ? </intent-filter> ??
</activity>
只有某個(gè)活動(dòng)能夠同時(shí)匹配<action>和<category>時(shí)宝鼓,才可以通過Intent來啟動(dòng)它巴刻。
? ?Intent intent = new Intent();
? ?intent.setAction("com.hm.intenttestdemo.ACTION.START");
? ?intent.addCategory(Intent.CATEGORY_DEFAULT);
? ?startActivity(intent);
初始化Intent蛉签,為intent設(shè)置Action碍舍,添加Category,此時(shí)系統(tǒng)會(huì)自動(dòng)幫助我們找到合適的需要啟動(dòng)的活動(dòng)妈经,系統(tǒng)如何找到呢捧书,這就回到了剛才我們?cè)谂渲梦募性O(shè)置的<intent-filter>標(biāo)簽的中的action和category了,如果同時(shí)滿足爆哑,則該活動(dòng)就是系統(tǒng)為我們找到的將要啟動(dòng)的最合適的活動(dòng)了舆吮。其實(shí)每個(gè)活動(dòng)在配置文件中聲明時(shí)色冀,都會(huì)默認(rèn)設(shè)置category參數(shù),默認(rèn)的值都為Intent.Category_Default敌卓,所以該屬性的設(shè)置通常使用時(shí)都省略設(shè)置了伶氢。
3.更多隱式Intent的用法
其實(shí)Intent的用法還有很多,設(shè)想一個(gè)應(yīng)用需要訪問一個(gè)網(wǎng)址蜗巧,就拿百毒來說吧蕾盯,我們可以在應(yīng)用內(nèi)做一個(gè)WebView活動(dòng)專門負(fù)責(zé)上網(wǎng),但是我們Android系統(tǒng)有自帶強(qiáng)大的瀏覽器應(yīng)用望拖,那如何在使用其他應(yīng)用時(shí)啟動(dòng)瀏覽器應(yīng)用呢说敏。通過下面的方法:
Intent intent =newIntent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("www.baidu.com"));
startActivity(intent);
這里我們首先設(shè)置Intent的Action是Intent.Action_View,這個(gè)是Android內(nèi)置的動(dòng)作,其常量值為android.intent.action.VIEW.然后通過parse()方法医咨,講一個(gè)字符串轉(zhuǎn)為Uri對(duì)象架诞。再調(diào)用setData()方法將Uri傳入谴忧。這樣就可以訪問系統(tǒng)的瀏覽器應(yīng)用了。
回顧之前Intent的隱式意圖的使用委造,在配置文件中<intent-filter>配置中也可以添加<data>標(biāo)簽搏屑,用于指定當(dāng)前活動(dòng)能夠響應(yīng)什么樣的數(shù)據(jù)類型。
android:scheme 用于指定數(shù)據(jù)的協(xié)議部分,如上例中的http部分
android:host 用于指定數(shù)據(jù)的主機(jī)名部分,如上列中的www.baidu.com
android:port 用于指定數(shù)據(jù)的端口部分,一般緊隨在主機(jī)名之后
android:path 用于指定主機(jī)名和端口之后的部分亮垫,如一段網(wǎng)址中跟在域名之后的內(nèi)容
android:mimeType 用于指定可以處理的數(shù)據(jù)類型伟骨,允許指定通配符的方式進(jìn)行指定携狭。
只有指定了<data>標(biāo)簽中的內(nèi)容和Intent中的攜帶的Data完全一致時(shí),當(dāng)前活動(dòng)才能夠響應(yīng)Intent.但是通常在<intent-filter>的<data>中稀并,都不會(huì)指定過多的內(nèi)容单默,比如上面的例子搁廓,只需要指定android:scheme為http耕皮,就可以響應(yīng)所有的http協(xié)議的Intent了蝙场。同樣的如果你同時(shí)配置了android:host為www.baidu.con時(shí)售滤,那Intent攜帶的data也只能為該Url地址才能響應(yīng)活動(dòng)。
當(dāng)然舟舒,除了http協(xié)議外嗜憔,我們還可以指定其他更多的協(xié)議氏仗,來調(diào)用系統(tǒng)的應(yīng)用為我們服務(wù)皆尔,比如相機(jī)(Camera),電話(Tel)珊拼,地理位置(Geo)等流炕。
4.Intent傳遞數(shù)據(jù)(向下)
當(dāng)我們通過Intent在各個(gè)活動(dòng)跳轉(zhuǎn)時(shí)每辟,避免不了需要傳遞數(shù)據(jù),在向目標(biāo)活動(dòng)傳遞數(shù)據(jù)時(shí)妹蔽,不管是通過顯示還是隱式的方式傳遞時(shí)挠将,系統(tǒng)提供了很多方便的Api供我們使用。
?Intent intent = new Intent(Context context,XXActivity.class);
?intent.putExtra("IngeterNum",12);
?intent.putExtra("DoubleNum",10.123);
?intent.putExtra("BooleanFlag",true);
?intent.putExtra("StringStr","haha");
?startActivity(intent);
當(dāng)然在目標(biāo)活動(dòng)頁乳丰,就是需要接受參數(shù)的活動(dòng)頁我們通過:
? Intent intent = getIntent();
? int intNum = intent.getIntExtra("IngeterNum",10); ?
? String str = intent.getStringExtra("StringStr");
我們可以發(fā)現(xiàn)在putExtra()方法中傳入的Key要與目標(biāo)活動(dòng)頁使用getXXExtra()方法接收參數(shù)時(shí)傳入的key要完全相同成艘,同時(shí)有的該方法需要你傳入一個(gè)默認(rèn)值,通扯象铮基本的參數(shù)類型只需要設(shè)置就可以使用了秋冰。
基本類型使用很簡單剑勾,如果我們需要傳遞對(duì)象怎么辦?其實(shí)也只是比基本類型稍微復(fù)雜一點(diǎn)暂刘,當(dāng)我們創(chuàng)建一個(gè)對(duì)象時(shí)捂刺,會(huì)接觸到一個(gè)對(duì)象可序列化的概念族展,通過類實(shí)現(xiàn)Serializable接口或者Parcelable。
4.1通過實(shí)現(xiàn)Serializable接口
傳遞數(shù)據(jù)
? Person p =newPerson();
? p.setAge(25);
? p.setName("張三");
? intent.putExtra("Person_Key",p);
? startActivity(intent);
接收數(shù)據(jù)
Person person = (Person)getIntent().getSerializableExtra("Person_Key");
同樣傳遞數(shù)據(jù)和接收數(shù)據(jù)時(shí)的Key要統(tǒng)一。
4.2通過轉(zhuǎn)為Json字符串傳遞
? 將對(duì)象類型轉(zhuǎn)為字符串類型恰画,也是數(shù)據(jù)傳遞的一種方式
傳遞數(shù)據(jù)
? Person p =newPerson();
? p.setAge(25);
? ?p.setName("張三");
? ?intent.putExtra("Person_Json_key",new Gson().toJson(p));
? ?startActivity(intent);
接收數(shù)據(jù)
String personJson = getIntent().getStringExtra("Person_Json_key");
Person p = newGson().fromJson(personJson,Person.class);
該方法主要使用Gson對(duì)象的方法锣尉,先將對(duì)象轉(zhuǎn)為String,再將String在目標(biāo)活動(dòng)界面接收后轉(zhuǎn)為對(duì)象坟奥。
4.3通過實(shí)現(xiàn)Parcelable接口
實(shí)現(xiàn)Parcelable接口需要實(shí)現(xiàn)兩個(gè)方法
describeContents方法拇厢。 內(nèi)容接口描述孝偎,默認(rèn)返回0就可以。
writeToParcel方法寺旺。 將傳遞的數(shù)據(jù)打包到Parcelable容器中。
除了要實(shí)現(xiàn)這兩個(gè)方法還必須要?jiǎng)?chuàng)建一個(gè)Parcelable.Creator接口的實(shí)例蓝撇,用于讀取Parcel容器中的數(shù)據(jù)
傳遞數(shù)據(jù)
Person p =newPerson();
p.setAge(25);
p.setName("張三");
intent.putExtra("Person_Json_key",new Gson().toJson(p));
startActivity(intent);
接收數(shù)據(jù)
Person person = (Person)getIntent().getSerializableExtra("Person_Key");
同樣傳遞數(shù)據(jù)和接收數(shù)據(jù)時(shí)的Key要統(tǒng)一渤昌。
簡化Parcel操作
如果你使用android Studio 可以通過安裝android-parce-intellij-plugin插件独柑,或者自己配置模板進(jìn)行操作私植。
5.Intent傳遞數(shù)據(jù)(向上)
Intent既然可以向下一個(gè)活動(dòng)傳遞數(shù)據(jù),自然也可以向上一個(gè)活動(dòng)傳遞數(shù)據(jù)狂秘,當(dāng)然返回上一個(gè)活動(dòng)只需要按一下設(shè)備的返回按鈕便會(huì)返回到上一個(gè)活動(dòng)躯肌。但是如何向上一個(gè)活動(dòng)傳遞數(shù)據(jù)呢清女?其實(shí)startActivity()方法是開啟一個(gè)新的活動(dòng)晰筛,startActivityForResult()方法也是開啟一個(gè)新活動(dòng)的方法读第,當(dāng)然該方法有兩個(gè)參數(shù),第一個(gè)參數(shù)毫無疑問是intent父泳,第二參數(shù)是一個(gè)整形參數(shù)的請(qǐng)求碼吴汪。
? ?Intent intent = new Intent(context,OtherActivity.class);
? ?startActivityForResult(intent,1);
我們來到剛才啟動(dòng)的OtherActivity活動(dòng)頁面漾橙,通過出發(fā)一個(gè)Button的點(diǎn)擊事件來返回到上一個(gè)活動(dòng)頁。
? ?((Button)findViewById(R.id.id_button)).setOnClickListener(new View.OnClickListener(){
? ? ? ? ? ? ? ? ? public void OnClick(View view){
? ? ? ? ? ? ? ? ? ? ? ? ?Intent intent = new Intent();
? ? ? ? ? ? ? ? ? ? ? ? ?intent.putExra("data_return","Hello FirstActivity");
? ? ? ? ? ? ? ? ? ? ? ? setResult(RESULT.OK,intent);
? ? ? ? ? ? ? ? ? ? ? ? finish();
? ? ? ? ? ? ? ? ? ? ?}
});
在button的點(diǎn)擊事件中脾歇,我們先創(chuàng)建了Intent對(duì)象,通過putExtra()方法為Intent添加需要傳遞的參數(shù)徽惋,調(diào)用活動(dòng)的setResult()方法险绘,然后finish()掉本活動(dòng)誉碴。注意setResult()方法,傳遞了兩個(gè)參數(shù)代咸,一個(gè)是RESULT.OK成黄,這個(gè)是系統(tǒng)的整形常量奋岁,與它相似的還有一個(gè)是RESULT.CANCELED,這兩個(gè)值代表的是向上返回的處理結(jié)果滨攻,intent中攜帶者需要向上傳遞的數(shù)據(jù).由于我們啟動(dòng)下一個(gè)活動(dòng)使用的是startActivityForResult()方法光绕,活動(dòng)就會(huì)調(diào)用onActivityResult()方法畜份,因此我們需要在FirstActivity中重寫這個(gè)方法:
?@Override
?protected void onActivityResult(int requestCode, int resultCode,Intent data) {
? ? switch(requestCode) {
? ? ? ? ? ?case1:
? ? ? ? ? ?if(resultCode ==RESULT_OK) {
? ? ? ? ? ? String returnData = data.getStringExtra("data_return");
? ? ? ? ?Log.d("FirstActivity",returnData);
? ? ? ? ?}
? ? ? ? break;
}
onActivityResult()方法有三個(gè)參數(shù)爆雹,第一個(gè)參數(shù)requestCode,即我們請(qǐng)求活動(dòng)跳轉(zhuǎn)時(shí)傳遞的請(qǐng)求碼谷徙,第二個(gè)參數(shù)時(shí)resultCode驯绎,即我們?cè)诜祷財(cái)?shù)據(jù)時(shí)傳入的處理結(jié)果剩失,第三個(gè)參數(shù)時(shí)Intent(data)册着,即返回?cái)y帶者的Intent脾歧。因?yàn)榭赡軙?huì)有多個(gè)地方在跳轉(zhuǎn)到其他活動(dòng)時(shí)調(diào)用startActivityForResult方法傳入不同的requestCode,在返回上一個(gè)頁面時(shí)調(diào)用setResult方法時(shí)鞭执,傳入不同的處理結(jié)果碼,所以我們?cè)诨卣{(diào)onActivityResult方法時(shí)需要通過盤點(diǎn)請(qǐng)求碼(requestCode)和返回碼(resultCode),來處理不同的邏輯大溜。