Activity的啟動(dòng)模式
1. 啟動(dòng)模式的類別
- 標(biāo)準(zhǔn)模式(standard)
- 棧頂復(fù)用模式(singleTop)
- 棧內(nèi)復(fù)用模式(singleTask)
- 單例模式(singleInstance)
2. 任務(wù)棧
任務(wù)棧Task,是一種用來放置Activity實(shí)例的容器讶凉,他是以棧的形式進(jìn)行盛放茬祷,也就是所謂的先進(jìn)后出,主要有2個(gè)基本操作:壓棧和出棧酪劫,其所存放的Activity是不支持重新排序的啊犬,只能根據(jù)壓棧和出棧操作更改Activity的順序。啟動(dòng)一個(gè)Application的時(shí)候蝶缀,系統(tǒng)會(huì)為它默認(rèn)創(chuàng)建一個(gè)對(duì)應(yīng)的Task,用來放置根Activity薄货。默認(rèn)啟動(dòng)Activity會(huì)放在同一個(gè)Task中翁都,新啟動(dòng)的Activity會(huì)被壓入啟動(dòng)它的那個(gè)Activity的棧中,并且顯示它谅猾。當(dāng)用戶按下回退鍵時(shí)柄慰,這個(gè)Activity就會(huì)被彈出棧,按下Home鍵回到桌面税娜,再啟動(dòng)另一個(gè)應(yīng)用坐搔,這時(shí)候之前那個(gè)Task就被移到后臺(tái),成為后臺(tái)任務(wù)棧敬矩,而剛啟動(dòng)的那個(gè)Task就被調(diào)到前臺(tái)概行,成為前臺(tái)任務(wù)棧,手機(jī)頁面顯示的就是前臺(tái)任務(wù)棧中的棧頂元素弧岳。
3. 四種啟動(dòng)模式的解釋
standard
標(biāo)準(zhǔn)模式:在清單文件中聲明 Activity 時(shí)凳忙,如果不設(shè)置Activity的啟動(dòng)模式,系統(tǒng)會(huì) 默認(rèn) 將其設(shè)置為standard
禽炬。每次啟動(dòng)一個(gè)標(biāo)準(zhǔn)模式的Activity都會(huì)重新創(chuàng)建一個(gè)新的實(shí)例涧卵,不管這個(gè)Activity之前是否已經(jīng)存在實(shí)例,一個(gè)任務(wù)棧中可以有多個(gè)實(shí)例腹尖,每個(gè)實(shí)例也可以屬于不同的任務(wù)棧柳恐,誰啟動(dòng)了這個(gè)Activity,那么這個(gè)Activity實(shí)例就運(yùn)行在啟動(dòng)它的那個(gè)Activity所在的棧中 热幔。根據(jù)上面所說乐设,我們就了解了當(dāng)用ApplicationContext啟動(dòng)或者在Service中直接調(diào)用startActivity啟動(dòng)標(biāo)準(zhǔn)模式Activity時(shí)報(bào)如下錯(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?
上面錯(cuò)誤的原因就是被啟動(dòng)的Activity是標(biāo)準(zhǔn)模式绎巨,而發(fā)起啟動(dòng)請(qǐng)求的Context不是Activity的Context近尚,未存在Activity棧,而每個(gè)Activity實(shí)例啟動(dòng)銷毀都需要進(jìn)棧出棧认烁,用棧來存儲(chǔ)Activity的信息肿男,所以非Activity Context需要設(shè)置FLAG_ACTIVITY_NEW_TASK
屬性,啟動(dòng)一個(gè)新的Activity棧却嗡。
singleTop
棧頂復(fù)用模式:在這種模式下,如果新啟動(dòng)的Activity已經(jīng)位于任務(wù)戰(zhàn)的棧頂嘹承,那么此Activity不會(huì)被重新創(chuàng)建窗价,只會(huì)重新調(diào)用 onNewIntent 方法,這個(gè)Activity的onCreate叹卷、onStart都不會(huì)被系統(tǒng)調(diào)用撼港。如果新Activity實(shí)例已經(jīng)存在但不在棧頂坪它,那么重新創(chuàng)建 Activity 并放入棧頂。
singleTask
棧內(nèi)復(fù)用模式:這是一種單實(shí)例模式帝牡,一個(gè)棧中同一個(gè)Activity只存在唯一一個(gè)實(shí)例往毡,無論是否在棧頂,只要存在實(shí)例靶溜,都不會(huì)重新創(chuàng)建开瞭,和 singleTop 一樣會(huì)重新調(diào)用 onNewIntent 方法。需要注意的是:如果一個(gè)Activity被設(shè)置為singleTask模式罩息,那么當(dāng)棧內(nèi)已經(jīng)存在該Activity實(shí)例時(shí)嗤详,再啟動(dòng)該Activity,會(huì)讓該Activity實(shí)例之上的Activity被出棧瓷炮。舉個(gè)例子:有四個(gè)Activity 分別是 A葱色、B、C和D,A是singleTask模式娘香,當(dāng)先執(zhí)行A->B->C->D時(shí)苍狰,A在棧內(nèi)已存在實(shí)例,此時(shí)再調(diào)用D->A啟動(dòng)A時(shí)烘绽,會(huì)讓A實(shí)例之上的B舞痰、C、D都出棧诀姚。一般項(xiàng)目的MainActivity都設(shè)置為此模式响牛,方便放回首頁和清空中間Activity英古。
singleInstance
單實(shí)例模式:這是一種加強(qiáng)的singleTask模式妆兑,它除了具有singleTask模式的所有特性外,還加強(qiáng)了一點(diǎn)豌研,那就是此種模式的Activity只能單獨(dú)地位于一個(gè)任務(wù)棧中糯笙,不同的應(yīng)用去打開這個(gè)activity 共享公用的同一個(gè)activity贬丛。他會(huì)運(yùn)行在自己?jiǎn)为?dú),獨(dú)立的任務(wù)棧里面给涕,并且任務(wù)棧里面只有他一個(gè)實(shí)例存在豺憔。應(yīng)用場(chǎng)景:呼叫來電界面。這種模式的使用情況比較罕見够庙,在Launcher中可能使用恭应。或者你確定你需要使Activity只有一個(gè)實(shí)例耘眨。
4. 啟動(dòng)模式的設(shè)置
啟動(dòng)模式有2種設(shè)置方式:在AndroidMainifest
設(shè)置昼榛、通過Intent
設(shè)置標(biāo)志位
4.1 在AndroidMainifest設(shè)置
在AndroidMainifest
的Activity
配置進(jìn)行設(shè)置
<activity
android:name="com.demo.Main4Activity"
//通過android:launchMode屬性設(shè)置
android:launchMode="singleTask"/>
4.2 通過Intent
設(shè)置標(biāo)志位
Intent inten = new Intent (ActivityA.this,ActivityB.class);
//通過Intent的Flag設(shè)置
intent,addFlags(Intent,FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
? 標(biāo)記為屬性
標(biāo)記位屬性 | 含義 |
---|---|
FLAG_ACTIVITY_SINGLE_TOP | 指定啟動(dòng)模式為棧頂復(fù)用模式(SingleTop ) |
FLAG_ACTIVITY_NEW_TASK | 指定啟動(dòng)模式為棧內(nèi)復(fù)用模式(SingleTask ) |
FLAG_ACTIVITY_CLEAR_TOP | 所有位于其上層的Activity都要移除,SingleTask 模式默認(rèn)具有此標(biāo)記效果 |