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