上篇文章Activity啓動模式一主要介紹了Activity的四種啓動模式,這些啓動模式都是在AndroidManifest
中進行配置的。除此以外,Android系統還經過Intent類提供了一些標誌位,一樣能夠指定Activity的啓動模式。本文將介紹下這些和Activity啓動相關的標誌位。java
通常狀況下,咱們在啓動目標Activity的Intent中指定這些標誌位,以下所示:android
Intent intent = new Intent();
intent.setClass(MainActivity.this,FirstActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
複製代碼
當同時在配置文件中指定launchMode和在Intent中指定上面的標誌位時,以標誌位爲準,即代碼的優先級比AndroidManifest的優先級更高!測試
下面咱們經過具體案例看下和Activity啓動相關的4種標誌位:this
官方文檔上介紹該標誌位和SingleTask啓動模式具備相同效果,其實否則。應該是FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP
一塊兒等同於SingleTask啓動模式。spa
這裏咱們經過4個案例,看下單獨使用FLAG_ACTIVITY_NEW_TASK標誌位和一塊兒使用FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_CLEAR_TOP標誌位的具體效果。3d
兩個Activity的taskAffinity屬性相同,具體步驟以下所示:code
通過MainActivity -> FirstActivity -> MainActivity
後,最終的任務棧以下所示: cdn
最後,MainActivity再次啓動FirstActivity後,最終的任務棧以下所示: blog
由於只有FLAG_ACTIVITY_NEW_TASK標誌位,沒有FLAG_ACTIVITY_CLEAR_TOP,因此沒法清除FirstActivity之上的MainActivity,複用已有FirstActivity。而是建立了新的FirstActivity。經過上面的任務棧可知:在taskAffinity相同的狀況下,單獨添加FLAG_ACTIVITY_NEW_TASK不起任何做用。文檔
兩個Activity的taskAffinity屬性不相同,具體步驟以下所示:
通過MainActivity -> FirstActivity -> MainActivity
後,最終的任務棧以下所示:
最後,MainActivity再次啓動FirstActivity後,最終的任務棧以下所示:
能夠看到,任務棧沒有發生任何變化,也沒有建立新的FirstActivity實例。這是由於FirstActivity實例已經存在於它所指望的任務棧中,而單獨添加FLAG_ACTIVITY_NEW_TASK標誌位又不會清除任務棧中位於FirstActivity之上的Activity實例,因此就沒有發生跳轉。經過上面的任務棧可知:在taskAffinity不一樣的狀況下,第一次啓動FirstActivity時,會新建一個任務棧,並將FirstActivity實例添加到該task中。這與SingleTask啓動模式產生的效果是一致的。可是,當企圖再次從MainActivity進入到FirstActivity時,卻什麼也沒有發生,緣由上面已經說明了。
綜上所述,單獨使用FLAG_ACTIVITY_NEW_TASK會產生很是奇怪的行爲,所以通常和FLAG_ACTIVITY_CLEAR_TOP標誌位一塊兒使用,這樣能夠實現相似SingleTask的效果,可是不徹底相同,下面會進行介紹。
下面咱們再經過兩個案例看下FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP
一塊兒使用的效果。
兩個Activity的taskAffinity屬性相同,具體步驟以下所示:
FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP
標誌位,啓動MainActivity的Intent不包含任何標誌位.通過MainActivity -> FirstActivity -> MainActivity
後,最終的任務棧以下所示:
最後,MainActivity再次啓動FirstActivity後,最終的任務棧以下所示:
貌似是和SingTask啓動模式的效果相同,可是細看一下就會發現區別: 先後兩次FirstActivity實例是不一樣的,也就是沒有複用第一次啓動的FirstActivity,而是清除了FirstActivity及其之上的全部Activity,而後新建FirstActivity實例添加到了當前任務棧。經過上面的任務棧可知:在taskAffinity相同的狀況下,FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP
標誌位組合確實不會建立新的任務棧,可是會清除了FirstActivity及其之上的全部Activity,並新建FirstActivity實例添加到了當前任務棧,這點是和SingleTask模式的差別。(SingleTask僅會清除FirstActivity之上的Activity,而後複用已有的FirstActivity)
兩個Activity的taskAffinity屬性不相同,具體步驟以下所示:
FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP
標誌位,啓動MainActivity的Intent不包含任何標誌位。通過MainActivity -> FirstActivity -> MainActivity
後,最終的任務棧以下所示:
最後,MainActivity再次啓動FirstActivity後,最終的任務棧以下所示:
能夠看到,和案例3 taskAffinity屬性相同的狀況相似(除了建立了新的任務棧),直接清除了FirstActivity及其之上的全部Activity,而後建立新的FirstActivity實例添加到新的任務棧(TaskId爲1980)。經過上面的任務棧可知:在taskAffinity不一樣的狀況下,FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP
標誌位組合會爲首次啓動的FirstActivity建立新的任務棧,其餘的邏輯與案例3基本相同,都是直接清除了FirstActivity及其之上的全部Activity,而後建立新的FirstActivity實例,這也是和SingleTask模式的區別。
綜上所述,FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP
標誌位組合產生的效果整體上和SingleTask模式相同,除了不會複用FirstActivity實例以外。
該標誌位在上面已經使用過了,做用是清除包含目標Activity的任務棧中位於該Activity實例之上的其餘Activity實例。可是是複用已有的目標Activity,仍是像上面那樣先刪除後重建,則有如下規則:
由於上面的案例3和案例4都不符合上面的兩條規則,因此FirstActivity纔會先被清除,而後重建。
下面咱們經過幾個具體案例,驗證下上面的兩條規則:
具體步驟以下所示:
FLAG_ACTIVITY_CLEAR_TOP
標誌位,啓動MainActivity的Intent不包含任何標誌位。通過MainActivity -> FirstActivity -> MainActivity
後,最終的任務棧以下所示:
最後,MainActivity再次啓動FirstActivity後,最終的任務棧以下所示:
經過上面的任務棧可知:第二次MainActivity -> FirstActivity
時,會先把FirstActivity以及之上的Activity所有銷燬,而後建立新的FirstActivity入棧,正符合咱們的預期。
具體步驟以下所示:
FLAG_ACTIVITY_CLEAR_TOP
標誌位,啓動MainActivity的Intent不包含任何標誌位。通過MainActivity -> FirstActivity -> MainActivity
後,最終的任務棧以下所示:
最後,MainActivity再次啓動FirstActivity後,最終的任務棧以下所示:
經過上面的任務棧可知:第二次MainActivity -> FirstActivity
時,會先把FirstActivity之上的Activity所有銷燬,而後複用已有的FirstActivity實例,也符合咱們的預期。
此外,當FirstActivity是SingleTask和SingleInstance模式時,其效果和SingleTop啓動模式同樣,也是首先銷燬FirstActivity之上的全部Activity,而後複用已有的FirstActivity實例。
這裏僅給出我驗證的任務棧: 當FirstActivity是SingleTask模式時(taskAffinity相同),通過MainActivity -> FirstActivity -> MainActivity
後,最終的任務棧以下所示:
最後,MainActivity再次啓動FirstActivity後,最終的任務棧以下所示:
可見,確實複用了已有的FirstActivity實例。當FirstActivity是SingleInstance模式時,通過MainActivity -> FirstActivity -> MainActivity
後,最終的任務棧以下所示:
最後,MainActivity再次啓動FirstActivity後,最終的任務棧以下所示:
可見,確實複用了已有的FirstActivity實例。綜上所述,經過案例1和案例2,咱們驗證了規則1是OK的。 下面咱們繼續驗證下規則2:
具體步驟以下所示:
FLAG_ACTIVITY_SINGLE_TOP + FLAG_ACTIVITY_CLEAR_TOP
標誌位,啓動MainActivity的Intent不包含任何標誌位。通過MainActivity -> FirstActivity -> MainActivity
後,最終的任務棧以下所示:
最後,MainActivity再次啓動FirstActivity後,最終的任務棧以下所示:
經過上面的任務棧可知:第二次MainActivity -> FirstActivity
時,會先把FirstActivity之上的Activity所有銷燬,而後複用已有的FirstActivity實例,也符合咱們的預期。
綜上所述,既然在FLAG_ACTIVITY_SINGLE_TOP + FLAG_ACTIVITY_CLEAR_TOP
標誌位組合的狀況下,Standard模式的FirstActivity都已經被複用了,那麼其餘啓動模式的Activity也必然會被複用。(單獨使用FLAG_ACTIVITY_CLEAR_TOP都會被複用,況且又添加了FLAG_ACTIVITY_SINGLE_TOP標誌位,經過Demo驗證也確實如此,就再也不給出具體案例了)。
綜上所述,上面的兩條規則還要是遵照的^_^。
該標誌位通常和FLAG_ACTIVITY_CLEAR_TASK一塊兒使用,目的是啓動目標Activity時,首先清空已經存在的目標Activity實例所在的任務棧,這天然也就清除了以前存在的目標Activity實例,而後建立新的目標Activity實例併入棧。
通過Demo測試發現,單獨使用FLAG_ACTIVITY_CLEAR_TASK標誌位,無論taskAffinity是否相同,都不會產生什麼效果。例以下面是單獨使用該標誌位的最終任務棧(taskAffinity相同 or 不一樣都是這樣):
感興趣的能夠自行嘗試,這裏再也不贅述。下面看下FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK
標誌位組合在taskAffinity相同 and 不一樣的狀況下的效果。
兩個Activity的taskAffinity屬性相同,具體步驟以下所示:
FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK
標誌位,啓動MainActivity的Intent不包含任何標誌位。第一次啓動MainActivity後,任務棧以下所示:
接着MainActivity啓動FirstActivity後,任務棧以下所示:
首先啓動的MainActivity竟然被清除了,而後才建立了FirstActivity實例。而後FirstActivity啓動MainActivity後,任務棧以下所示:
最後MainActivity再次啓動FirstActivity後,任務棧以下所示:
可見,系統再次清除了FirstActivity及其之上的MainActivity,而後從新建立了新的FirstActivity實例併入棧。經過上面的任務棧可知:當經過FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK
標誌位組合啓動FirstActivity時,首先會清空FirstActivity所在的任務棧,而後再建立新的FirstActivity實例併入棧。
兩個Activity的taskAffinity屬性不相同,具體步驟以下所示:
FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK
標誌位,啓動MainActivity的Intent不包含任何標誌位。第一次MainActivity啓動FirstActivity後,任務棧以下所示:
由於taskAffinity不一樣,因此爲FirstActivity實例建立了新的任務棧。而後FirstActivity啓動MainActivity後,任務棧以下所示:
最後MainActivity再次啓動FirstActivity後,任務棧以下所示:
可見,系統首先清除了任務棧(TaskId爲2040)中FirstActivity及其之上的MainActivity,而後從新建立了新的FirstActivity實例併入棧(TaskId爲2040)。經過上面的任務棧可知:當經過FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK
標誌位組合啓動FirstActivity時,首先會清空FirstActivity所在的任務棧,而後再建立新的FirstActivity實例併入棧,這和taskAffinity屬性相同是一致的效果,只不過這裏第一次爲FirstActivity建立了新的任務棧。
綜上所述,當經過FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK
標誌位組合啓動目標Activity時,首先會清空目標Activity所在的任務棧(若目標Activity是第一次啓動,那麼會清空目標Activity所指望的任務棧),而後建立新的目標Activity實例併入棧。
該標誌單獨使用就能夠達到SingleTop啓動模式的效果,該類效果能夠參考前篇文章,這裏再也不贅述。
這裏簡單介紹一些AndroidManifest
配置文件中與啓動模式相關的屬性。其實前一篇文章已經介紹了兩個比較經常使用的屬性:android:taskAffinity
和android:allowTaskReparenting
,下面再補充一些不經常使用的屬性。
字面意思是:是否在啓動時清除任務棧,該屬性默認爲false,表示是否在APP啓動時,清除任務棧中除根Activity以外的其餘Activity實例。該屬性只對任務棧內的根Activity起做用,任務棧內其餘的Activity都會被忽略。
好比:咱們有一個App,依次啓動了ActivityA、ActivityB和ActivityC,其中ActivityA和ActivityB都設置clearTaskOnLaunch屬性爲true。那麼首先點擊「Home」建回到Launcher界面,而後再啓動該App,咱們看到是ActivityA界面,而ActivityB和ActivityC都被銷燬了。 除非棧底的ActivityA已經被銷燬,那麼上面設置clearTaskOnLaunch屬性爲true的activity(B)纔會生效。
該屬性默認值爲false,表示當離開當前Activity所在的任務棧時,當即銷燬當前Activity,而其餘Activity不受影響。
該屬性默認值爲false,表示App的任務棧是否保持原來的狀態。該屬性只對task的根Activity起做用,其餘的Activity都會被忽略。 默認狀況下,若一個App在後臺停留的時間太長,那麼再啓動該App時,系統會清除任務棧中除了根Activity以外的其餘Activity,可是若是根Activity設置了該屬性,那麼再次啓動應用時,就不會清除Task中的Activity,而是保持原樣,所以仍然能夠看到上一次操做的界面。
OK,Activity啓動模式相關的內容就介紹這些吧,但願對本身對感興趣的同窗都有所幫助^_^。