Android中的任務棧和Activity的啟動模式
一、Android中的任務棧
在Android系統中,任務棧是一種用來存放Activity實例的容器。通常當一個Android應用程序啟動時,如果當前環境中不存在該應用程序的任務棧,那么系統就會創建一個任務棧。此后,這個應用程序所啟動的Activity都將在這個任務棧中被管理。需要特別注意的是,一個任務棧中的Activity可以來自不同的App,同一個App的Activity也可能不在一個任務棧中。
任務棧的較大特點是先進后出。根據Activity當前棧結構中的位置,來決定該Activity的狀態。正常情況下,Android任務棧的工作情況如下圖所示:
Activity1處于棧頂位置,當在Activity1中開啟Activity2時,Activity2的實例會被壓入棧頂的位置。
同樣,在Activity2中開啟Activity3時,Activity3的實例也會被壓入棧頂的位置。以此類推,無論開啟多少個Activity,最后開啟的Activity的實例都會被壓入棧的頂端,而之前開啟的Activity雖然“功成身退”,卻仍然保存在棧中,但活動已經停止。系統會保存Activity被停止時的狀態。
當用戶點擊返回按鈕或者調用finish()方法時,Activity3會被彈出棧,Activity2處于棧頂位置并恢復Activity2被保存的界面狀態。
當然任務棧的這種工作特性并不完美,因此可以給Activity設置一些“特權”,來打破這種“和諧”的模式。這種“特權”也就是下面我們將探討的Activity的啟動模式。
二、Activity的啟動模式
Activity啟動模式有4種,分別是standard、singleTop、singleTask和singleInstance模式。
1.standard模式(標準模式)
standard模式是Activity的默認啟動方式,每啟動一個Activity就會在棧頂創建一個新的實例。因此,這種啟動模式下會存在大量相同的實例。當然,這種模式下也允許存在相同的實例。
在實際開發中,鬧鐘程序通常使用這種模式。
例如:創建一個啟動模式為standard的ActivityA,點擊A跳轉到A頁面,點擊兩次 A->A->A,這樣棧內就會出現三個相同的A實例,這時候點擊返回鍵的時候你就會發現,我們需要點擊三次返回鍵才能退出頁面。
2.singleTop模式(棧頂復用模式)
在某些情況下,會發現使用standard模式啟動的Activity并不合理。例如,當Activity已經位于棧頂,再次啟動該Activity還需要創建一個新的實例壓入任務棧,而不能直接復用之前的Activity實例。
在這種情況下,使用singleTop模式啟動Activity更合理,該模式會判斷要啟動的Activity實例是否位于棧頂,如果位于棧頂,則直接復用,否則創建新的實例。實際開發中,瀏覽器的書簽采用這種模式。
例如:創建兩個Activity A和B,將B的啟動模式設置成SingleTop。點擊A跳轉到B,點擊B跳轉到B?, A->B->B?這時候點擊返回按鈕的時候,只需要點擊一次就返回到A頁面了。
3.singleTask模式(棧內復用模式)
使用singleTop模式雖然可以很好的解決棧頂重復壓入Activity實例的問題。但如果要啟動的Activity的未處于棧頂,則還會在棧中壓入多個不相連的Activity實例。需要Activity在棧中有且只有一個實例,借助singleTask模式可以實現。
當Activity的啟動模式指定為singleTask時,每次啟動該Activity時,系統會首先檢查棧中是否存在當前的Activity實例,如果存在,直接使用該Activity,并將當前Activity的實例上面的所有實例全部彈出棧。實際開發中,瀏覽器主界面通常采用這張模式。
例如:創建兩個Activity A和B,將A的啟動模式設置成SingleTask。點擊A跳轉到B,點擊B跳轉到A?, A->B->A?這時候點擊返回按鈕的時候,點擊一次就退出頁面了。
4.singleInstance模式
singleInstance模式是4種啟動模式中最特殊的一種,指定singleInstance模式的Activity會啟動一個新的任務棧來管理該Activity實例,無論從哪個任務棧中啟動該Activity,該Activity實例在整個系統中都只有一個。Android的桌面使用的就是該模式。
啟動singleInstance模式的Activity有兩種情況:
情況一:要啟動的Activity實例在棧中不存在,系統先創建一個新的任務棧,然后壓入Activity。
情況二:要啟動的Activity實例已存在,系統把該Activity所在的任務棧轉移到前臺,從而使Activity展示。
實際開發中,來電界面通常使用該模式。
例如創建三個Activity A、B、C,將B的啟動模式設置成singleInstance,點擊A跳轉到B,點擊B跳轉到C,這時候點擊返回按鈕,你會發現會從C直接返回到A而不是B。因為B和A、C不是一個任務棧,B是單獨、獨立的一個任務棧。