3.2.2 Activity的啟動模式大全

1搞监、啟動一個Activity的幾種方式

在Android中我們可以通過下面兩種方式來啟動一個新的Activity,注意這里是怎么啟動璃哟,而非 啟動模式L仁恰黄虱!分為顯示啟動和隱式啟動!

1. 顯式啟動:通過包名來啟動白热,寫法如下:

①最常見的:
startActivity(new Intent(當前Act.this,要啟動的Act.class));
②通過Intent的ComponentName:ComponentName cn = new ComponentName("當前Act的全限定類名","啟動Act的全限定類名") ;Intent intent = new Intent() ;intent.setComponent(cn) ;startActivity(intent) ;
③初始化Intent時指定包名:Intent intent = new Intent("android.intent.action.MAIN");intent.setClassName("當前Act的全限定類名","啟動Act的全限定類名");startActivity(intent);

2.隱式啟動:通過Intent-filter的Action,Category或data來實現(xiàn) 這個是通過Intent的intent-filter來實現(xiàn)的敛助。
3. 另外還有一個直接通過包名啟動apk的:

Intent intent = getPackageManager().getLaunchIntentForPackage("apk第一個啟動的Activity的全限定類名") ;
if(intent != null) startActivity(intent) ;

2、Activity的管理

我們來看下官方文檔給出的一個流程圖:


流程解析:
應(yīng)用程序中存在A1,A2,A3三個activity屋确,當用戶在Launcher或Home Screen點擊應(yīng)用程序圖標時纳击, 啟動主A1续扔,接著A1開啟A2,A2開啟A3评疗,這時棧中有三個Activity,并且這三個Activity默認在 同一個任務(wù)(Task)中茵烈,當用戶按返回時百匆,彈出A3,棧中只剩A1和A2呜投,再按返回鍵加匈, 彈出A2,棧中只剩A1仑荐,再繼續(xù)按返回鍵雕拼,彈出A1,任務(wù)被移除粘招,即程序退出啥寇!

3、Task的管理

Task是Activity的集合洒扎,是一個概念辑甜,實際使用的Back Stack來存儲Activity,可以有多個Task袍冷,但是 同一時刻只有一個棧在最前面磷醋,其他的都在后臺!那棧是如何產(chǎn)生的呢胡诗?

答:當我們通過主屏幕邓线,點擊圖標打開一個新的App,此時會創(chuàng)建一個新的Task煌恢!舉個例子:我們通過點擊通信錄APP的圖標打開APP骇陈,這個時候會新建一個棧1,然后開始把新產(chǎn)生的Activity添加進來瑰抵,可能我們在通訊錄的APP中打開了短信APP的頁面缩歪,但是此時不會新建一個棧,而是繼續(xù)添加到棧1中谍憔,這是 Android推崇一種用戶體驗方式匪蝙,即不同應(yīng)用程序之間的切換能使用戶感覺就像是同一個應(yīng)用程序, 很連貫的用戶體驗习贫,官方稱其為seamless (無縫銜接)逛球! 這個時候假如我們點擊Home鍵,回到主屏幕苫昌,此時棧1進入后臺颤绕,我們可能有下述幾種操作:

  • 點擊菜單鍵(正方形那個按鈕),點擊打開剛剛的程序,然后棧1又回到前臺了奥务! 又或者我們點擊主屏幕上通信錄的圖標物独,打開APP,此時也不會創(chuàng)建新的棧氯葬,棧1回到前臺挡篓!
  • 如果此時我們點擊另一個圖標打開一個新的APP,那么此時則會創(chuàng)建一個新的棧2帚称,棧2就會到前臺官研, 而棧1繼續(xù)呆在后臺;

后面也是這樣闯睹,以此類推戏羽!

如上面所述,Android會將新成功啟動的Activity添加到同一個Task中并且按照以"先進先出"方式管理多個Task 和Back Stack楼吃,用戶就無需去擔心Activites如何與Task任務(wù)進行交互又或者它們是如何存在于Back Stack中始花! 或許,你想改變這種正常的管理方式孩锡。比如衙荐,你希望你的某個Activity能夠在一個新的Task中進行管理; 或者你只想對某個Activity進行實例化浮创,又或者你想在用戶離開任務(wù)時清理Task中除了根Activity所有Activities忧吟。你可以做這些事或者更多,只需要通過修改AndroidManifest.xml中 <activity>的相關(guān)屬性值或者在代碼中通過傳遞特殊標識的Intent給startActivity()就可以輕松的實現(xiàn) 對Actvitiy的管理了斩披。

Activity是安卓上最聰明的設(shè)計之一溜族,優(yōu)秀的內(nèi)存管理讓多任務(wù)完美運行在最流行的操作系統(tǒng)之上。并不是讓Activity在屏幕上啟動就完事了垦沉,其啟動方式也是需要關(guān)注的煌抒。這個話題的內(nèi)容很多,其中很重要的就是啟動模式厕倍。

Activity的啟動模式對我們來說應(yīng)該是個全新的概念寡壮,在實際項目中我們應(yīng)該根據(jù)特定的需求為每個Activity指定恰當?shù)膯幽J健幽J揭还灿兴姆N讹弯,分別是 standard况既、 singleTop、singleTask 和 singleInstance组民,可以在 AndroidManifest.xml 中通過給 <activity>標簽指定android:launchMode 屬性來選擇啟動模式棒仍,下面我們來逐個進行學(xué)習(xí)。

一臭胜、standard模式

standard 是Activity默認的啟動模式莫其,在不進行顯式指定的情況下癞尚,所有Activity都會自動使用這種啟動模式。因此乱陡,到目前為止我們寫過的所有Activity都是使用的 standard 模式浇揩。經(jīng)過之前的學(xué)習(xí),我們已經(jīng)知道了 Android 是使用返回棧來管理活動的憨颠,在 standard 模式(即默認情況)下胳徽,每當啟動一個新的Activity,它就會在返回棧中入棧烙心,并處于棧頂?shù)奈恢媚だ取τ谑褂?standard 模式的活動乏沸,系統(tǒng)不會在乎這個Activity是否已經(jīng)在返回棧中存在淫茵,每次啟動都會創(chuàng)建該Activity的一個新的實例。

也就是說在這種模式下啟動的Activity可以被多次實例化蹬跃,即在同一個任務(wù)中可以存在多個Activity的實例匙瘪,每個實例都會處理一個Intent對象。如果Activity A的啟動模式為standard蝶缀,并且A已經(jīng)啟動丹喻,在A中再次啟動Activity A,即調(diào)用startActivity(new Intent(this翁都,A.class))碍论,會在A的上面再次啟動一個A的實例,即當前的桟中的狀態(tài)為A --> A柄慰。


下面的圖片顯示了向標準啟動模式的Activity分享照片時的情況鳍悠。雖然分別來自不同的應(yīng)用,但仍然它會和發(fā)送intent的Activity處于同一個任務(wù)中坐搔。


在Lollipop設(shè)備上的表現(xiàn):
如果Activity都是來自同一個應(yīng)用藏研,其表現(xiàn)和Lollipop之前的設(shè)備一樣,在任務(wù)的頂端:

但是如果intent來自其他應(yīng)用概行,將創(chuàng)建一個新的任務(wù)蠢挡,同時新創(chuàng)建的Activity會被作為一個根Activity,如下:


下面是任務(wù)管理器中的樣子:

發(fā)生這種情況的原因是Lollipop中任務(wù)管理系統(tǒng)做了修改凳忙,讓它看起來更合理了业踏。因為它們在不同的任務(wù)中,你可以直接切回Gallery涧卵,你還可以觸發(fā)另一個Intent堡称,創(chuàng)建新的與之前相同的任務(wù)。


standard6.jpg

撰寫郵件的Activity或者發(fā)布社交網(wǎng)絡(luò)狀態(tài)的Activity都是采用這種Activity的例子艺演。如果你希望Activity單獨服務(wù)于一個Intent却紧,就可以考慮standard啟動模式桐臊。

二、singleTop模式

可能在有些情況下晓殊,你會覺得 standard 模式不太合理断凶。Activity明明已經(jīng)在棧頂了,為什么再次啟動的時候還要創(chuàng)建一個新的活動實例呢巫俺?別著急认烁,這只是系統(tǒng)默認的一種啟動模式而已,我們完全可以根據(jù)自己的需要進行修改介汹,比如說使用 singleTop 模式却嗡。當Activity的啟動模式指定為 singleTop,在啟動活動時如果發(fā)現(xiàn)返回棧的棧頂已經(jīng)是該活動嘹承,則認為可以直接使用它窗价,不會創(chuàng)建新的實例,而是重用位于棧頂?shù)哪莻€實例叹卷, 并且會調(diào)用該實例的onNewIntent()方法將Intent對象傳遞到這個實例中撼港。

舉例來說,如果A的啟動模式為singleTop骤竹,并且A的一個實例已經(jīng)存在于棧頂中帝牡, 那么再調(diào)用startActivity(new Intent(this,A.class))啟動A時蒙揣, 不會再次創(chuàng)建A的實例靶溜,而是重用原來的實例,并且調(diào)用原來實例的onNewIntent()方法懒震。 這時任務(wù)棧中還是這有一個A的實例罩息。如果以singleTop模式啟動的Activity的一個實例 已經(jīng)存在與任務(wù)棧中,但是不在棧頂挎狸,那么它的行為和standard模式相同扣汪,也會創(chuàng)建多個實例。


三锨匆、singleTask模式

使用 singleTop 模式可以很好地解決重復(fù)創(chuàng)建棧頂活動的問題崭别,但是正如上面所說的,如果該Activity并沒有處于棧頂?shù)奈恢每致啵€是可能會創(chuàng)建多個Activity實例的茅主。那么有沒有什么辦法可以讓某個Activity在整個應(yīng)用程序的上下文中只存在一個實例呢?這就要借助singleTask 模式來實現(xiàn)了土榴。

當Activity的啟動模式指定為 singleTask诀姚,每次啟動該Activity時系統(tǒng)首先會在返回棧中檢查是否存在該Activity的實例,如果發(fā)現(xiàn)已經(jīng)存在則直接使用該實例玷禽,并把在這個Activity之上的所有Activity統(tǒng)統(tǒng)出棧赫段,如果沒有發(fā)現(xiàn)就會創(chuàng)建一個新的Activity實例呀打。

但是如果已經(jīng)存在,singleTask Activity上面的所有Activity將以合適的方式自動銷毀糯笙,讓我們想要顯示的Activity處于棧頂贬丛。同時Intent也會通過onNewIntent()方法發(fā)送到這個singleTask Activity。


官方文檔中提到的一個問題:系統(tǒng)會創(chuàng)建一個新的任務(wù)给涕,并將這個Activity實例化為新任務(wù)的根部(root) 這個則需要我們對taskAffinity進行設(shè)置了豺憔,使用taskAffinity后的結(jié)果:


和其他應(yīng)用一起工作的情況:一旦intent是從另外的應(yīng)用發(fā)送過來,并且系統(tǒng)中也沒有任何Activity的實例够庙,則會創(chuàng)建一個新的任務(wù)恭应,并且新的Activity被作為根Activity創(chuàng)建。


如果這個singleTask Activity 的應(yīng)用已經(jīng)存在耘眨,那么新建的Activity會置于這個任務(wù)的上面(而不是新建一個任務(wù))昼榛。


假設(shè)已經(jīng)有了一個Activity的實例,不管它是在哪個任務(wù)中(包括上面的那種情況毅桃,在用于這個Activity的應(yīng)用中)褒纲,整個任務(wù)將被移到頂端准夷,而singleTask Activity上面的所有 Activity 都將被銷毀钥飞, 用戶需要按back鍵遍歷完棧中的Activity才能回到調(diào)用者任務(wù)。



這種模式的應(yīng)用案例有:郵件客戶端的收件箱或者社交網(wǎng)絡(luò)的時間軸衫嵌。這些Activity一般不會設(shè)計成擁有多個實例读宙,singleTask可以滿足。但是在使用這種模式的時候必須要明智楔绞,因為有些Activity會在用戶不知情的情況下被銷毀结闸。

四、singleInstance模式

singleInstance 模式應(yīng)該算是四種啟動模式中最特殊也最復(fù)雜的一個了酒朵, 我們也需要多花點功夫來理解這個模式桦锄。不同于以上三種啟動模式,指定為 singleInstance 模式的Activity會啟用一個新的返回棧來管理這個Activity(其實如果 singleTask 模式指定了不同的 taskAffinity蔫耽,也會啟動一個新的返回棧)结耀。那么這樣做有什么意義呢?

想象以下場景匙铡,假設(shè)我們的程序中有一個Activity是允許其他程序調(diào)用的图甜,如果我們想實現(xiàn)其他程序和我們的程序可以共享這個Activity的實例,應(yīng)該如何實現(xiàn)呢鳖眼?使用前面三種啟動模式肯定是做不到的黑毅,因為每個應(yīng)用程序都會有自己的返回棧,同一個Activity在不同的返回棧中入棧時必然是創(chuàng)建了新的實例钦讳。而使用 singleInstance 模式就可以解決這個問題矿瘦,在這種模式下會有一個單獨的返回棧來管理這個Activity枕面,不管是哪個應(yīng)用程序來訪問這個Activity,都共用的同一個返回棧缚去,也就解決了共享Activity實例的問題膊畴。

還有一點需要注意:當我們再次啟動該Activity的實例時,會重用已存在的任務(wù)和實例病游,并且會調(diào)用這個實例的onNewIntent()方法唇跨,將Intent實例傳遞到該實例中。和singleTask相同衬衬,同一時刻在系統(tǒng)中只會存在一個這樣的Activity實例买猖。


不過結(jié)果卻很怪異,從顯示結(jié)果來看滋尉,似乎系統(tǒng)中有兩個任務(wù)但任務(wù)管理器中只顯示一個玉控,即最后被移到頂部的那個。導(dǎo)致雖然后臺有一個任務(wù)在運行狮惜,我們卻無法切換回去高诺,這一點也不科學(xué)。

下面是當 singleInstance Activity 被調(diào)用的同時棧中已經(jīng)有一些Activity的情況下所發(fā)生的事情:


本來有兩個任務(wù)碾篡,但是任務(wù)管理器中卻只顯示一個任務(wù):


SingleInstance3.jpg

因為這個任務(wù)只有一個Activity虱而,我們再也無法切回到 任務(wù)#1 了,唯一的辦法是重新在launcher中啟動這個應(yīng)用开泽。

不過這個問題也有解決方案牡拇,就像我們在singleTask Acvity中做的,只要為singleInstance Activity設(shè)置taskAffinity屬性就可以了:

<activity
            android:name=".SingleInstanceActivity"
            android:label="singleInstance launchMode"
            android:launchMode="singleInstance"
            android:taskAffinity="">

現(xiàn)在就變得正常多了:



這種模式很少被使用穆律,實際使用的案例如Launcher的Activity或者100%確定只有一個Activity的應(yīng)用惠呼。總之除非完全有必要峦耘,不然我不建議使用這種模式剔蹋。

Intent Flags:

除了在AndroidManifest.xml中直接設(shè)置launch mode,我們還可以通過叫做 Intent Flags 的東西設(shè)置更多的行為辅髓,比如:

Intent intent = new Intent(StandardActivity.this, StandardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);

這段代碼將會啟動一個singleTop啟動模式的的StandardActivity 泣崩。

點此進入:GitHub開源項目“愛閱”

感謝優(yōu)秀的你跋山涉水看到了這里利朵,歡迎關(guān)注下讓我們永遠在一起律想!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市绍弟,隨后出現(xiàn)的幾起案子技即,更是在濱河造成了極大的恐慌,老刑警劉巖樟遣,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件而叼,死亡現(xiàn)場離奇詭異身笤,居然都是意外死亡宣羊,警方通過查閱死者的電腦和手機寥袭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門七冲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粥喜,“玉大人,你說我怎么就攤上這事胃惜〕疲” “怎么了并扇?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵绊困,是天一觀的道長文搂。 經(jīng)常有香客問我,道長秤朗,這世上最難降的妖魔是什么煤蹭? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮取视,結(jié)果婚禮上硝皂,老公的妹妹穿的比我還像新娘。我一直安慰自己作谭,他們只是感情好稽物,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著丢早,像睡著了一般姨裸。 火紅的嫁衣襯著肌膚如雪秧倾。 梳的紋絲不亂的頭發(fā)上怨酝,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機與錄音那先,去河邊找鬼农猬。 笑死,一個胖子當著我的面吹牛售淡,可吹牛的內(nèi)容都是我干的斤葱。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼揖闸,長吁一口氣:“原來是場噩夢啊……” “哼揍堕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起汤纸,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤衩茸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后贮泞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楞慈,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡幔烛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了囊蓝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饿悬。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖聚霜,靈堂內(nèi)的尸體忽然破棺而出狡恬,到底是詐尸還是另有隱情,我是刑警寧澤蝎宇,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布傲宜,位于F島的核電站,受9級特大地震影響夫啊,放射性物質(zhì)發(fā)生泄漏函卒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一撇眯、第九天 我趴在偏房一處隱蔽的房頂上張望报嵌。 院中可真熱鬧,春花似錦熊榛、人聲如沸锚国。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽血筑。三九已至,卻和暖如春煎楣,著一層夾襖步出監(jiān)牢的瞬間豺总,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工择懂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留喻喳,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓困曙,卻偏偏與公主長得像表伦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子慷丽,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容