在Android的開發(fā)項(xiàng)目中裕照,Activity(活動)是最容易吸引到用戶的地方,因?yàn)橄啾扔谒惴ǖ魉⒓軜?gòu)晋南,它是實(shí)際可見的紫皇。
Activity是一個可以包含用戶界面的組件雳窟,主要用于和用戶進(jìn)行交互。一個用戶程序可以包含零個(沒什么意義)或多個活動颖杏。
我們已經(jīng)能熟的練創(chuàng)建活動并使用控件和布局來做美觀的界面了姜凄,但對于活動本身與活動間的跳轉(zhuǎn)(借助于intent)恐怕還并不了解政溃。(本系列的android開發(fā)環(huán)境均為Eclipse)
創(chuàng)建android活動詳見《Android開發(fā)(一) 創(chuàng)建第一個活動》
控件、布局的使用和實(shí)例詳見《Android開發(fā)(二) 編寫程序界面》
最難用的控件ListView使用和實(shí)例詳見《Android開發(fā)(三) 最常用和最難用的控件》
這一章我們就來探究活動和Intent的使用态秧。由基本的活動開始董虱,一步步深入。(本章內(nèi)容較長申鱼,請先喝口水找個舒服的坐姿愤诱,再來耐心閱讀;熟悉的部分可直接略過)
一捐友、活動的基本組成與用法
1)打開任意一個工程(這里筆者新建了一個project转锈,命名為Test),首先可以發(fā)現(xiàn)我們創(chuàng)建的活動都應(yīng)該重寫Activity的onCreate()方法:
之后我們再繼續(xù)往里加自己的邏輯楚殿。另外這里還調(diào)用了setContentView()方法來給當(dāng)前的活動加載一個布局,一般我們會在其中傳入一個布局文件的id(activity_main即ADT自動生成的布局文件id)竿痰。
2)打開res目錄下的layout文件脆粥,會發(fā)現(xiàn)ADT自動生成了一個名為activity_main.xml的布局。當(dāng)我們沒有往里添加控件時(shí)影涉,代碼很簡潔:
這個布局就是在主活動MainActivity的setContentView()方法中默認(rèn)加載的布局变隔,只不過它現(xiàn)在是空的。
3)所有的活動都要在AndroidManifest.xml中進(jìn)行注冊才能生效⌒非悖現(xiàn)在我們打開AndroidManifest.xml:
注冊聲明放在了<application>標(biāo)簽內(nèi)匣缘,這里是通過<activity>標(biāo)簽對活動進(jìn)行注冊的猖闪。MainActivity的注冊信息就放在這個標(biāo)簽下。android:name來指定具體注冊哪個活動肌厨,android:label指定活動中標(biāo)題欄內(nèi)容培慌。
如果我們要讓MainActivity作為此程序的主活動,即點(diǎn)擊應(yīng)用程序圖標(biāo)時(shí)首先打開的就是這個活動柑爸,那一定記得在<intent-filter>標(biāo)簽下吵护,加入這兩句聲明:
4)部分人可能覺得標(biāo)題欄相當(dāng)占用屏幕空間,使得內(nèi)容區(qū)域變小了表鳍。
因此不少應(yīng)用程序選擇將標(biāo)題欄隱藏馅而。隱藏的方法非常簡單,打開MainActivity譬圣,在onCreate()方法中添加一行代碼即可:
5)創(chuàng)建活動已變得非常簡單瓮恭,那如何銷毀一個活動呢?
其實(shí)只要按一下Back鍵就可以銷毀當(dāng)前活動了厘熟。如果你希望在程序中通過代碼銷毀活動屯蹦,當(dāng)然完全可以。Activity類提供了一個finish()方法盯漂,我們在控件中加入一個按鈕颇玷,然后在MainActivity的onCreate()方法下,修改按鈕的點(diǎn)擊事件函數(shù)即可:
重新運(yùn)行程序就缆,點(diǎn)擊一下按鈕當(dāng)前的活動就被銷毀了帖渠,效果和按下Back鍵一致。
二竭宰、使用Intent在活動之間穿梭
只有一個活動的應(yīng)用是不是太easy了空郊?
我們在工程Test中再創(chuàng)建一個活動:右鍵工程下的src文件夾→new→Android Activity,接下來就和創(chuàng)建第一個活動時(shí)的步驟一樣了切揭,只要改一下新建活動的名稱(如命名為SecondActivity)即可狞甚。
現(xiàn)在你無論創(chuàng)建多少個活動都輕而易舉,關(guān)鍵是怎樣才能由主活動(MainActivity)跳轉(zhuǎn)到其他活動呢廓旬?我們來好好看一看哼审。
1)使用顯示intent
我們已經(jīng)在同一個工程Test中創(chuàng)建了兩個活動,現(xiàn)在打開AndroidManifest.xml孕豹,可以發(fā)現(xiàn)注冊信息已經(jīng)更新:
SecondActivity不是主活動涩盾,所以不需要配置<intent-filter>標(biāo)簽里的內(nèi)容。接著我們要引入一個新的概念:Intent励背,就是通過它來啟動這第二個活動春霍。
Intent是Android程序中各組件之間進(jìn)行交互的一種重要方式,它不僅可以指明當(dāng)前組件想要執(zhí)行的動作叶眉,還可以在不同組件之間傳遞數(shù)據(jù)址儒。Intent一般可被用于啟動活動芹枷、啟動服務(wù)、發(fā)送廣播等場景莲趣,本章我們自然鎖定在啟動活動上鸳慈。
Intent用法大致分兩種:顯式Intent和隱式Intent,先來看常用的顯式Intent的用法妖爷。
Intent有多個構(gòu)造函數(shù)的重載蝶涩,其中一個是Intent(Context packageContext,Class<?>cls)。這個構(gòu)造函數(shù)接收兩個參數(shù)絮识,第一個參數(shù)Context要求提供一個啟動活動的上下文绿聘,第二個Class指定要啟動的目標(biāo)活動。
Activity類中提供了一個startActivity()方法專門用于啟動活動次舌,它接收一個Intent參數(shù)熄攘。我們將構(gòu)建好的Intent傳入startActivity()就能啟動目標(biāo)活動了。
我們先在activity_main.xml中定義一個按鈕彼念,按鈕上顯示Button 1:
接著在MainActivity中給按鈕注冊一個監(jiān)聽器挪圾,并修改按鈕的點(diǎn)擊事件,代碼如下:
我們構(gòu)建了一個Intent逐沙,傳入MainActivity.this作為上下文哲思,傳入SecondActivity.class作為目標(biāo)活動,這樣我們的“意圖”變得很明顯了吩案。最后通過startActivity()方法來執(zhí)行這個Intent棚赔。
重新運(yùn)行程序,在MainActivity界面點(diǎn)擊一下按鈕徘郭,結(jié)果如圖:
我們已經(jīng)成功啟動SecondActivity這個活動了靠益。如果你想回到上一活動,按下Back鍵當(dāng)前活動就會銷毀残揉,從而回到上一個活動了胧后。
2)使用隱式Intent
相比于顯示Intent,隱式Intent則含蓄了很多抱环,它并不明確指出我們想要啟動哪一個活動壳快,而是指定了一系列更為抽象的action和category等信息,然后交由系統(tǒng)去分析這個Intent镇草,并找出合適的活動去啟動眶痰。
這就是隱式Intent的工作原理,限于篇幅這兒不再展開詳解陶夜。我們直接來看隱式Intent的一種用法實(shí)例:除了啟動自己程序內(nèi)的活動,還可以啟動其他程序的活動裆站。
程序運(yùn)行結(jié)果如下:
這是一個自定義的瀏覽器首頁界面条辟,具體控件的定義黔夭、布局不再贅余。我們可以給圖標(biāo)(如百度)加入響應(yīng)事件羽嫡,當(dāng)點(diǎn)擊圖標(biāo)時(shí)自動打開對應(yīng)的網(wǎng)頁本姥。
在活動中,寫入圖標(biāo)響應(yīng)的代碼(以“百度”為例):
Intent.ACTION_VIEW是一個Android系統(tǒng)內(nèi)置動作杭棵,然后通過Uri.parse()方法婚惫,將一個網(wǎng)址字符串解析成一個Uri對象,再調(diào)用Intent的setData()方法將Uri對象傳入魂爪。
其它關(guān)于Intent隱式的用法先舷,感興趣讀者可以自行查閱安卓開發(fā)的文檔。
3)向下一個活動傳遞數(shù)據(jù)
上一節(jié)我們簡單地使用Intent來啟動一個活動滓侍,其實(shí)Intent還可以在啟動活動的時(shí)候傳遞數(shù)據(jù)蒋川。
思路其實(shí)很簡單,Intent中提供了一系列putExtra()方法的重載撩笆,可以把我們想要傳遞的數(shù)據(jù)暫存在Intent中捺球。啟動另一活動后,只需要把這些數(shù)據(jù)再從Intent中取出即可夕冲。
比如MainActivity中有一個字符串氮兵,現(xiàn)在想把這個字符串傳遞到SecondActivity中,可以這樣編寫:
我們使用顯式Intent的方式來啟動SecondActivity歹鱼,并通過putExtra()方法傳遞了一個字符串泣栈。注意這里putExtra()方法接收兩個參數(shù),第一個參數(shù)是鍵醉冤,用于后面從Intent中取值秩霍,第二個參數(shù)才是真正要傳遞的數(shù)據(jù)。
然后我們在SecondActivity中將傳遞的數(shù)據(jù)取出蚁阳,順便打印出來:
首先通過getIntent()方法獲取用于啟動SecondActivity的Intent铃绒;然后調(diào)用getStringExtra()方法,傳入相應(yīng)鍵值螺捐,就可以得到傳遞的數(shù)據(jù)了颠悬。
這里我們傳遞了字符串,所以使用getStringExtra()方法定血,如果傳遞整型數(shù)據(jù)赔癌,就使用getIntExtra()方法;傳遞布爾型數(shù)據(jù)澜沟,用getBooleanExtra()方法灾票,以此類推。
重新運(yùn)行程序茫虽,在MainActivity界面點(diǎn)擊一下按鈕會跳轉(zhuǎn)到SecondActivity刊苍,查看LogCat打印信息:
4)返回?cái)?shù)據(jù)給上一個活動
既然可以傳遞數(shù)據(jù)給下一個活動既们,當(dāng)然也可以返回?cái)?shù)據(jù)給上一個活動啦。不同的是正什,返回上一活動只需要按下Back鍵即可啥纸,并沒有一個用于啟動活動Intent來傳遞數(shù)據(jù)。
查閱文檔可以發(fā)現(xiàn)婴氮,Activity中還有一個startActivityForResult()方法同樣用于啟動活動斯棒,但這個方法期望在活動銷毀時(shí)能夠返回一個結(jié)果給上一個活動。對主经,這就是我們需要的荣暮。
startActivityForResult()方法接收兩個參數(shù),第一個參數(shù)還是Intent旨怠,第二個參數(shù)是請求碼渠驼,用于在之后的回調(diào)中判斷數(shù)據(jù)的來源。我們還是繼續(xù)來實(shí)戰(zhàn)鉴腻,修改MainActivity中按鈕的點(diǎn)擊事件:
這里我們使用startActivityForResult()方法啟動SecondActivity迷扇,請求碼只要是唯一值就行,這里傳入1爽哎。接著我們給SecondActivity的布局加一個按鈕Button2蜓席,然后為它注冊點(diǎn)擊事件:
我們還是構(gòu)建了一個Intent,只不過這個Intent僅用于傳遞數(shù)據(jù)而已课锌。緊接著把要傳遞的數(shù)據(jù)存放在Intent中厨内,再調(diào)用setResult()方法。
這個方法很重要渺贤,是專門用于向上一個活動返回?cái)?shù)據(jù)的雏胃。setResult()方法接收兩個參數(shù):第一個參數(shù)用于向上一個活動返回處理結(jié)果;第二個參數(shù)則把帶有數(shù)據(jù)的Intent傳遞回去志鞍。最后調(diào)用了finish()銷毀當(dāng)前活動瞭亮。
因?yàn)槲覀兪褂昧藄tartActivityForResult()方法啟動第二個活動,在SecondActivity被銷毀后會回調(diào)上一個活動的onActivityResult()方法固棚,所以我們需要在MainActivity中重寫這個方法來得到返回的數(shù)據(jù):
onActivityResult()方法帶三個參數(shù):requestCode是我們啟動活動是傳入的請求碼统翩;resultCode是我們返回?cái)?shù)據(jù)是傳入的處理結(jié)果;data是攜帶有返回?cái)?shù)據(jù)的Intent此洲。
由于在同個活動中有可能調(diào)用startActivityForResult()方法去啟動很多不同的活動厂汗,每個活動返回的數(shù)據(jù)都會回調(diào)到onActivityResult()中。因此我們首先要做的就是檢查requestCode的值來判斷數(shù)據(jù)來源呜师。
確定數(shù)據(jù)是從SecondActivity返回后娶桦,再通過requestCode的值來判斷處理結(jié)果是否成功。最后從data中取值并打印,這樣就完成了向上一個活動返回?cái)?shù)據(jù)的工作衷畦。
重新啟動程序氮双,在MainActivity界面點(diǎn)擊按鈕會打開SecondActivity,然后在SecondActivity點(diǎn)擊Button2按鈕會回到MainActivity霎匈,這時(shí)查看LogCat的打印信息:
還有一個小問題:如果用戶在SecondActivity中沒有點(diǎn)擊按鈕,而是直接按Back鍵返回了MainActivity送爸,數(shù)據(jù)不就沒法返回了嗎铛嘱?
的確是這樣沒錯。不過我們可以通過重寫onBackPressed()方法來解決這個問題:
現(xiàn)在袭厂,用戶按下Back鍵墨吓,程序就會執(zhí)行onBackPressed()方法中的代碼,我們在里面添加返回?cái)?shù)據(jù)的邏輯即可纹磺。
5)最佳實(shí)踐
結(jié)合以上所學(xué)習(xí)的活動和Intent知識帖烘,我們程序的活動變得靈活了許多,最后我們看一個活動間數(shù)據(jù)傳遞的簡單實(shí)例橄杨。
還是借用之前章節(jié)提到過的火車票查詢系統(tǒng)秘症。首先是首次進(jìn)入時(shí),程序界面的展示:
這兒的數(shù)據(jù)是我們手動在MainActivity中初始化傳入寫死的式矫,在本系列接下來的文章中乡摹,我們馬上會使用從文檔或sqlite安卓數(shù)據(jù)庫中動態(tài)讀取數(shù)據(jù)的方式。
接著我們點(diǎn)擊最下方的“修改信息”按鈕采转,程序會跳轉(zhuǎn)到另一個“修改”的活動界面聪廉,當(dāng)然還是借助于Intent,只不過用putExtra()多傳遞了幾個參數(shù):
跳轉(zhuǎn)后可以看到這樣的界面故慈,只是一些控件和布局的組合:
點(diǎn)擊修改的+板熊、-號按鈕,相應(yīng)數(shù)字和顏色(rgb值)會改變:
當(dāng)然我們并不滿足于此察绷,我們的最終目的是回傳修改后的數(shù)據(jù)并作用到上一個活動的界面上干签。
在SecondActivity中的onCreate()方法獲得傳遞而來的數(shù)據(jù),代碼應(yīng)該不需要展示了克婶。最后來看點(diǎn)擊“確定“后用Intent的putExtra()回傳數(shù)據(jù)的邏輯:
重寫MainActivity活動的onActivityResult()得到返回的數(shù)據(jù)筒严,最后通過適配器把參數(shù)作用到控件上整個過程就完成啦。來看看效果情萤,應(yīng)該和之前預(yù)想的一致:
怎么樣鸭蛙,還不錯吧。我們的數(shù)據(jù)已經(jīng)能靈活的傳遞筋岛、修改娶视、回傳、使用了。
本章小節(jié):經(jīng)過這張學(xué)習(xí)肪获,我們成功漲了不少知識:大致明白Android中活動的構(gòu)成寝凌、使用Intent向下一個活動傳遞數(shù)據(jù)、從下一個活動返回?cái)?shù)據(jù)給上一個活動等等孝赫,還是收獲頗多的较木。
現(xiàn)在我們的程序可以隨意調(diào)用多個活動了,增強(qiáng)了項(xiàng)目的靈活性和互動性青柄,距離優(yōu)良的用戶體驗(yàn)應(yīng)該說貼近了一大步伐债。
真正熟練掌握數(shù)據(jù)的傳遞依舊需要:多敲代碼,多實(shí)戰(zhàn)致开,多參考文檔資料峰锁。長期堅(jiān)持,編程双戳、開發(fā)虹蒋、設(shè)計(jì)的水平定會平穩(wěn)提升。
本章到此完結(jié)飒货,感謝您能抽空閱讀魄衅!如有收獲不妨點(diǎn)贊留下您的足跡:)
作者:葉琛
癡迷編程和旅行的IT程序狗