說到啟動模式,先介紹下android的任務棧,任務棧是一種后進先出的結構。位于棧頂的Activity處于焦點狀態,當按下back按鈕的時候,棧內的Activity會一個一個的出棧,并且調用其onDestory()方法。如果棧內沒有Activity,那么系統就會回收這個棧,每個APP默認只有一個棧,以APP的包名來命名.
而Android就是通過使用android:launchMode="standard|singleInstance|singleTask|singleTop"這四種啟動模式來控制Acivity任務棧。
具體如下:
1、standard
標準模式,每次啟動Activity都會創建一個新的Activity實例,并且將其壓入任務棧棧頂,而不管這個Activity是否已經存在。Activity的啟動三回調(onCreate()->onStart()->onResume())都會執行。
2、singleTop
棧頂復用模式.這種模式下,如果新Activity已經位于任務棧的棧頂,那么此Activity不會被重新創建,所以它的啟動三回調就不會執行,同時Activity的onNewIntent()方法會被回調.如果Activity已經存在但是不在棧頂,那么作用于standard模式一樣.
舉例:A(standard),B(singleTop)
A ——>B——>B : B的onNewIntent()會被調用, 棧內(A-B)
A ——>B——>A——>B :棧內(A-B-A-B)。(不在棧頂時的跳轉就跟standard方式一樣)
3、singleTask
棧內復用模式.創建這樣的Activity的時候,系統會先確認它所需任務棧已經創建,否則先創建任務棧.然后放入Activity,如果棧中已經有一個Activity實例,那么這個Activity就會被調到棧頂,onNewIntent(),并且singleTask會清理在當前Activity上面的所有Activity.(clear top)
舉例:A(standard),B(singleTask)
A ——>B——>B : B的onNewIntent()會被調用, 棧內(A-B)(跟singleTop表現一樣)
A ——>B——>A——>B :B的onNewIntent()會被調用, 棧內(A-B)
應用場景:
需求說明:
如果自己的客戶端處于運行狀態,按下Home鍵后臺掛起。此時如果使用微信調起自己的客戶端某 個頁面,不做任何處理的情況下,按下回退或者當前 Activity.finish(),頁面都會停留在自己的客戶端(因為自己的Application回 退棧不為空),這明顯不符合邏輯的。產品的要求 是,回退必須回到微信客戶端,而且要保證不殺死自己的Application.
處理方案:
設置當前 被調起Activity的屬性 為:LaunchMode=""SingleTask" taskAffinity="com.tencent.mm"(com.tencent.mm 是借助于工具找到的微信包名),就是把自己的 Activity放到微信默認的Task棧里面,這樣回退時就會遵循“Task只要有Activity一定 從本Task剩余Activity回退"的原 則,不會回到自己的客戶端,而且也不會影響自己客戶端本來的Activity和Task邏輯。
taskAffinity 屬性主要和singleTask或者allowTaskReparenting屬性配對使用,其他情況下無意義
4、singleInstance
設置為 singleInstance 模式的 activity 將獨占一個task(感覺task可以理解為進程),獨占一個task的activity與其說是activity,倒不如說是一個應用,這個應用與其他activity是獨立的,它有自己的上下文activity。
舉例:A(standard),B(singleInstance)
A ——>B——>B : B的onNewIntent()會被調用, 兩個棧:棧A(A),棧B(B)
A ——>B——>A——>B :B的onNewIntent()會被調用, 兩個棧:棧A(A-A),棧B(B)