Android 四大啟動(dòng)模式

Activity 的 LaunchMode

默認(rèn)情況下,多次啟動(dòng)同一個(gè) Activity 時(shí),系統(tǒng)會(huì)創(chuàng)建多個(gè)實(shí)例并把它們一一放入任務(wù)棧中,當(dāng)我們按 back 健時(shí),這些 Activity 會(huì)一一回退。任務(wù)棧是一種“后進(jìn)先出”的棧結(jié)構(gòu),即每按一下 back 健就會(huì)有一個(gè) Activity 出棧,直到??諡橹?,當(dāng)棧中無任何 Activity 時(shí),系統(tǒng)會(huì)回收這個(gè)任務(wù)棧。

四種啟動(dòng)模式:standard、singleTop、singleTask 和 singleInstance。下面介紹各種啟動(dòng)模式的含義及使用例子。

一、standard – 默認(rèn)模式

standard:標(biāo)準(zhǔn)模式也是系統(tǒng)的默認(rèn)模式。每次啟動(dòng)一個(gè) Activity 都會(huì)重新創(chuàng)建一個(gè)新的實(shí)例,不管這個(gè)實(shí)例是否已經(jīng)存在。這種模式下,誰啟動(dòng)了這個(gè) Activity,那么這個(gè) Activity 就運(yùn)行在啟動(dòng)它的那個(gè) Activity 所在的棧中。如 Activity A 啟動(dòng)了 Activity B(B 是標(biāo)準(zhǔn)模式),那么 B 就會(huì)進(jìn)入到 A 所在的棧中。

當(dāng)我們用 ApplicationContext 去啟動(dòng) standard 模式的 Activity 時(shí)會(huì)報(bào)錯(cuò),錯(cuò)誤如下:

android.util.AndroidRuntimeException: Calling startActivity() from outside
of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. 
Is this really what you want?

這是因?yàn)?standard 模式的 Activity 默認(rèn)會(huì)進(jìn)入啟動(dòng)它的 Activity 所屬的任務(wù)棧中,由于非 Activity 類型的 Context (如 ApplicationContext)并沒有所屬的任務(wù)棧,所以就出問題了。解決方法是為待啟動(dòng) Activity 指定 FLAG_ACTIVITY_NEW_TASK 標(biāo)記位,這樣啟動(dòng)的時(shí)候會(huì)創(chuàng)建一個(gè)新的任務(wù)棧,這時(shí)待啟動(dòng)的 Activity 是以 singleTask 模式啟動(dòng)的

二、singleTop – 棧頂復(fù)用模式

singleTop 棧頂復(fù)用模式。如果新 Activity 已經(jīng)位于任務(wù)棧的棧頂,那么此 Activity 不會(huì)被重新創(chuàng)建,同時(shí)它的 onNewIntent 方法會(huì)被調(diào)用,通過此方法的參數(shù)可以取出當(dāng)前請(qǐng)求的信息。需要注意的是,這個(gè) Activity 的 onCreate、onStart 不會(huì)被系統(tǒng)重新調(diào)用,因?yàn)樗]有發(fā)生改變。如果新 Activity 的實(shí)例已經(jīng)存在但不是位于棧頂,那么新 Activity 仍然會(huì)重建。

適合接收通知啟動(dòng)的內(nèi)容顯示頁面,當(dāng)收到多條新聞推送時(shí),用于展示新聞的 Activity 設(shè)置成此模式,根據(jù)傳來的 Intent 數(shù)據(jù)顯示不同的新聞信息,不會(huì)啟動(dòng)多個(gè) Activity。

三、singleTask – 棧內(nèi)復(fù)用模式

singleTask:棧內(nèi)復(fù)用模式。這是一種單實(shí)例模式,在這種模式下,只要 Activity 在一個(gè)棧中存在,那么多次啟動(dòng)此 Activity 都不會(huì)重新創(chuàng)建實(shí)例,復(fù)用時(shí)會(huì)將它上面的 Activity 全部出棧,同時(shí)它的 onNewIntent 方法會(huì)被調(diào)用。這個(gè)過程存在一個(gè)任務(wù)棧匹配,因?yàn)檫@個(gè)模式啟動(dòng)時(shí)會(huì)在自己需要的任務(wù)棧中尋找實(shí)例,這個(gè)任務(wù)棧通過 taskAffinity 屬性指定,如果這個(gè)任務(wù)棧不存在,則會(huì)創(chuàng)建這個(gè)任務(wù)棧。

taskAffinity 標(biāo)識(shí)了一個(gè) Activity 所需的任務(wù)棧的名字,默認(rèn)情況下,所有 Activity 所需的任務(wù)棧的名字為應(yīng)用的包名。我們可以為每個(gè) Activity 都單獨(dú)指定 TaskAffinity 屬性,這個(gè)屬性必須不能和包名相同,否則就相當(dāng)于沒有指定。TaskAffinity 屬性主要和 singleTask 啟動(dòng)模式或者 allowTaskReparenting 屬性配對(duì)使用。另外,任務(wù)棧分為前臺(tái)任務(wù)棧和后臺(tái)任務(wù)棧,后臺(tái)任務(wù)棧中的 Activity 處于暫停狀態(tài),用戶可以通過切換將后臺(tái)任務(wù)棧再次調(diào)到前臺(tái)。

適合作為程序入口點(diǎn),例如瀏覽器的主界面,不管從多少個(gè)應(yīng)用啟動(dòng)瀏覽器,只會(huì)啟動(dòng)主界面一次,其余情況都會(huì)走 onNewIntent,并且會(huì)清空主界面上的其它頁面

四、singleInstance – 單實(shí)例模式

singleInstance:?jiǎn)螌?shí)例模式。該模式除了具備 singleTask 模式的所有特性外,該模式的 Activity 只能單獨(dú)的位于一個(gè)任務(wù)棧中,具有全局唯一性,即整個(gè)系統(tǒng)中只有這一個(gè)實(shí)例,由于棧內(nèi)復(fù)用的特性,后續(xù)的請(qǐng)求均不會(huì)創(chuàng)建新的Activity實(shí)例,除非這個(gè)特殊的任務(wù)棧被銷毀了。以singleInstance模式啟動(dòng)的Activity在整個(gè)系統(tǒng)中是單例的,如果在啟動(dòng)這樣的Activiyt時(shí),已經(jīng)存在了一個(gè)實(shí)例,那么會(huì)把它所在的任務(wù)調(diào)度到前臺(tái),重用這個(gè)實(shí)例

如何指定 Activity 的啟動(dòng)模式?

(1)通過 AndroidMenifest 為 Activity 指定啟動(dòng)模式,如下所示:

<activity
     android:name=".activity.protocol.ProtocolActivity"
     android:launchMode="singleTask"/>

(2)通過 Intent 中設(shè)置標(biāo)志位來為 Activity 指定啟動(dòng)模式,如下所示:

Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

優(yōu)先級(jí)上第二種優(yōu)先級(jí)高于第一種,當(dāng)兩種同時(shí)存在時(shí),以第二種方式為準(zhǔn);這兩種方式的限定方式不同,第一種無法直接為 Activity 設(shè)定 FLAG_ACTIVITY_CLEAR_TOP 標(biāo)識(shí),第二種無法為 Activity 指定 singleInstance 模式。

Activity 常用 Flags
FLAG_ACTIVITY_NEW_TASK

為 Activity 指定 singleTask 啟動(dòng)模式,效果和在 XML 中指定該模式相同

FLAG_ACTIVITY_SINGLE_TOP

為 Activity 指定 singleTop 啟動(dòng)模式,效果和在 XML 中指定該模式相同

FLAG_ACTIVITY_CLEAR_TOP

具有此標(biāo)記的 Activity,當(dāng)它啟動(dòng)時(shí),在同一個(gè)任務(wù)棧中所有位于它上面的 Activity 都要出棧

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

具有這個(gè)標(biāo)記的 Activity 不會(huì)出現(xiàn)在歷史 Activity 的列表中,在某些情況下我們不希望用戶通過歷史列表回到我們的 Activity 的時(shí)候這個(gè)標(biāo)記比較有用。它等同于在 XML 中指定 Activity 的屬性 android:excludeFromRecents="true"。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容