準(zhǔn)備知識(shí)
為什么需要啟動(dòng)模式
在Android開(kāi)發(fā)中,我們都知道,在默認(rèn)的情況下,如果我們啟動(dòng)的是同一個(gè)Activity的話,系統(tǒng)會(huì)創(chuàng)建多個(gè)實(shí)例并把它們一一放入任務(wù)棧中。當(dāng)我們點(diǎn)擊返回(back)鍵,這些Activity實(shí)例又將從任務(wù)棧中一一移除,遵循的原則是“后進(jìn)先出”(先進(jìn)后出)。
這里我們考慮一個(gè)問(wèn)題,當(dāng)我們多次啟動(dòng)同一個(gè)Activity,系統(tǒng)也會(huì)創(chuàng)建多個(gè)實(shí)例放入任務(wù)棧中,這樣豈不是很耗費(fèi)內(nèi)存資源?為了解決這一問(wèn)題,Android為Actiivty提供了啟動(dòng)模式。啟動(dòng)模式
Activity的啟動(dòng)模式有四種:standard、singleTop、singleTask和singleInstance。-
如何使用
<activity android:name=".DemoActivity" <!-- value 可以設(shè)為啟動(dòng)模式中任意一種,默認(rèn)standard --> android:launchMode="singleTop" > </activity>
啟動(dòng)模式的分類(lèi)
標(biāo)準(zhǔn)模式:standard
- 這種啟動(dòng)模式為標(biāo)準(zhǔn)模式,也是
默認(rèn)模式 - 每當(dāng)我們啟動(dòng)一個(gè)Activity,系統(tǒng)就會(huì)相應(yīng)的創(chuàng)建一個(gè)實(shí)例,不管這個(gè)實(shí)例是否已經(jīng)存在
- 這種模式,一個(gè)棧中可以有多個(gè)實(shí)例,每個(gè)實(shí)例也都有自己的任務(wù)棧。而且是誰(shuí)啟動(dòng)了此Activity,那么這個(gè)Activity就運(yùn)行在啟動(dòng)它的Activity所在的棧中。
- 【跨進(jìn)程】這種方式啟動(dòng)的Activity被跨進(jìn)程調(diào)用
- 系統(tǒng)5.0之前:新啟動(dòng)的Activity實(shí)例會(huì)放入發(fā)送Intent的Task的棧的頂部,盡管它們屬于不同的程序,這似乎有點(diǎn)費(fèi)解看起來(lái)也不是那么合理
- 系統(tǒng)5.0之后:上述情景會(huì)創(chuàng)建一個(gè)新的Task,新啟動(dòng)的Activity就會(huì)放入剛創(chuàng)建的Task中,這樣就合理的多了
棧頂復(fù)用模式:singleTop
- 當(dāng)前棧中不存在該Activity的實(shí)例時(shí):其行為同standard啟動(dòng)模式
- 當(dāng)前棧中已有該Activity的實(shí)例并且該實(shí)例位于棧頂時(shí):不會(huì)創(chuàng)建實(shí)例,而是復(fù)用棧頂?shù)膶?shí)例,并且會(huì)將Intent對(duì)象傳入,回調(diào)onNewInten()方法
- 當(dāng)前棧中已有該Activity的實(shí)例但是該實(shí)例不在棧頂時(shí):其行為和standard啟動(dòng)模式一樣,依然會(huì)創(chuàng)建一個(gè)新的實(shí)例
- 【跨進(jìn)程】這種方式啟動(dòng)的Activity被跨進(jìn)程調(diào)用表現(xiàn)同standard
棧內(nèi)復(fù)用模式:singleTask
在復(fù)用的時(shí)候,首先會(huì)根據(jù)taskAffinity去找對(duì)應(yīng)的任務(wù)棧:
- 如果不存在指定的任務(wù)棧,系統(tǒng)會(huì)新建對(duì)應(yīng)的任務(wù)棧,并新建Activity實(shí)例壓入棧中
- 如果存在指定的任務(wù)棧,則會(huì)查找該任務(wù)棧中是否存在該Activity實(shí)例
a、如果不存在該實(shí)例,則會(huì)在該任務(wù)棧中新建Activity實(shí)例
b、如果存在該實(shí)例,則會(huì)直接引用,并且回調(diào)該實(shí)例的onNewIntent()方法。并且任務(wù)棧中該實(shí)例之上的Activity會(huì)被全部銷(xiāo)毀 - 【跨進(jìn)程】這種方式啟動(dòng)的Activity被跨進(jìn)程調(diào)用表現(xiàn)同standard
單實(shí)例模式:singleInstance
該實(shí)例為系統(tǒng)唯一,不同的應(yīng)用去打開(kāi)這個(gè)activity 共享公用的同一個(gè)activity。他會(huì)運(yùn)行在自己?jiǎn)为?dú),獨(dú)立的任務(wù)棧里面,并且任務(wù)棧里面只有他一個(gè)實(shí)例存在。啟動(dòng)該模式Activity的時(shí)候,會(huì)查找系統(tǒng)中是否存在:
- 不存在,首先會(huì)新建一個(gè)任務(wù)棧,其次創(chuàng)建該Activity實(shí)例
- 存在,則會(huì)直接引用該實(shí)例,并且回調(diào)onNewIntent()方法
LaunchMode Flag
Activity 的啟動(dòng)模式除了在 AndroidManifest 文件中設(shè)置以外,還可以通過(guò) Intent的 Flag 來(lái)設(shè)置:
FLAG_ACTIVITY_NEW_TASK
使用一個(gè)新的任務(wù)棧 Task 來(lái)啟動(dòng)一個(gè) Activity,但啟動(dòng)的每個(gè)Activity都將在一個(gè)新的任務(wù)棧 Task 中。該 Flag 通常使用在從Service 中啟動(dòng) Activity 的場(chǎng)景,由于Service中并不存在Activity 任務(wù)棧,所以使用該 Flag 來(lái)創(chuàng)建一個(gè)新的Activity棧,并創(chuàng)建新的 Activity 實(shí)例。FLAG_ACTIVITY_SINGLE_TOP
使用 singletop 模式啟動(dòng)一個(gè)Activity, 當(dāng)這個(gè)Activity位于歷史stack的頂端運(yùn)行時(shí),不再創(chuàng)建一個(gè)新的Activity實(shí)例;
與指定android:launchMode=“singleTop”效果相同FLAG_ACTIVITY_CLEAR_TOP
銷(xiāo)毀目標(biāo)Activity和它之上的所有Activity,重新創(chuàng)建目標(biāo)Activity
與指定android:launchMode=“singleTask”效果相同FLAG_ACTIVITY_NO_HISTORY
一個(gè) Activity 使用這種模式啟動(dòng)后,當(dāng)該 Activity 啟動(dòng)其他Activity后,該 Activity 自己就消失了,不會(huì)保留在Activity棧中。FLAG_ACTIVITY_BROUGHT_TO_FRONT
在launchMode中設(shè)置singleTask模式時(shí)系統(tǒng)會(huì)設(shè)定。FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
如果設(shè)置,新的Activity不會(huì)在最近啟動(dòng)的Activity的列表中保存。FLAG_ACTIVITY_FORWARD_RESULT
如果設(shè)置,并且這個(gè)Intent用于從一個(gè)存在的Activity啟動(dòng)一個(gè)新的Activity,那么,這個(gè)作為答復(fù)目標(biāo)的Activity將會(huì)傳到這個(gè)新的Activity中。這種方式下,新的Activity可以調(diào)用setResult(int),并且這個(gè)結(jié)果值將發(fā)送給那個(gè)作為答復(fù)目標(biāo)的 Activity。FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
這個(gè)標(biāo)志一般不由應(yīng)用程序代碼設(shè)置,如果這個(gè)Activity是從歷史記錄里啟動(dòng)的(常按HOME鍵),系統(tǒng)會(huì)設(shè)定。
任務(wù)棧
任務(wù)棧Task,是一種用來(lái)放置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,用來(lái)放置根Activity。默認(rèn)啟動(dòng)Activity會(huì)放在同一個(gè)Task中,新啟動(dòng)的Activity會(huì)被壓入啟動(dòng)它的那個(gè)Activity的棧中,并且顯示它。當(dāng)用戶(hù)按下回退鍵時(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ù)棧,Android系統(tǒng)顯示的就是前臺(tái)任務(wù)棧中的Top實(shí)例Activity。