天天看點

【Android】Activity的四種launchMode

合抱之木,生於毫末;九層之台,起於累土;千裡之行,始於足下。《老子》

今天在社群看到有朋友問“如何在半年内成為頂級架構師”,有網友道“關燈睡覺,不用半年的...”,的确,做夢還來的快一些。作為一個程式員,樹立遠大的目标是值得欣賞的,但不能隻去空想,要一步一步地實踐才行。成大事者,須從小事做起;萬事起于忽微,量變引起質變。

我們今天要講的是activity的四種launchmode。

launchmode在多個activity跳轉的過程中扮演着重要的角色,它可以決定是否生成新的activity執行個體,是否重用已存在的activity執行個體,是否和其他activity執行個體公用一個task裡。這裡簡單介紹一下task的概念,task是一個具有棧結構的對象,一個task可以管理多個activity,啟動一個應用,也就建立一個與之對應的task。

activity一共有以下四種launchmode:

1.standard

2.singletop

3.singletask

4.singleinstance

我們可以在androidmanifest.xml配置<activity>的android:launchmode屬性為以上四種之一即可。

下面我們結合執行個體一一介紹這四種lanchmode:

standard模式是預設的啟動模式,不用為<activity>配置android:launchmode屬性即可,當然也可以指定值為standard。

我們将會一個activity,命名為firstactivity,來示範一下标準的啟動模式。firstactivity代碼如下:

【Android】Activity的四種launchMode
【Android】Activity的四種launchMode
【Android】Activity的四種launchMode

如圖所示,每次跳轉系統都會在task中生成一個新的firstactivity執行個體,并且放于棧結構的頂部,當我們按下後退鍵時,才能看到原來的firstactivity執行個體。

這就是standard啟動模式,不管有沒有已存在的執行個體,都生成新的執行個體。

我們在上面的基礎上為<activity>指定屬性android:launchmode="singletop",系統就會按照singletop啟動模式處理跳轉行為。我們重複上面幾個動作,将會出現下面的現象:

【Android】Activity的四種launchMode
【Android】Activity的四種launchMode
【Android】Activity的四種launchMode

正如上圖所示,跳轉時系統會先在棧結構中尋找是否有一個firstactivity執行個體正位于棧頂,如果有則不再生成新的,而是直接使用。也許朋友們會有疑問,我隻看到棧内隻有一個activity,如果是多個activity怎麼辦,如果不是在棧頂會如何?我們接下來再通過一個示例來證明一下大家的疑問。

我們再建立一個activity命名為secondactivity,如下:

然後将之前的firstactivity跳轉代碼改為:

是的,firstactivity會跳轉到secondactivity,secondactivity又會跳轉到firstactivity。示範結果如下:

【Android】Activity的四種launchMode
【Android】Activity的四種launchMode
【Android】Activity的四種launchMode

我們看到,兩個firstactivity的序列号是不同的,證明從secondactivity跳轉到firstactivity時生成了新的firstactivity執行個體。原理圖如下:

【Android】Activity的四種launchMode

我們看到,當從secondactivity跳轉到firstactivity時,系統發現存在有firstactivity執行個體,但不是位于棧頂,于是重新生成一個執行個體。

這就是singletop啟動模式,如果發現有對應的activity執行個體正位于棧頂,則重複利用,不再生成新的執行個體。

【Android】Activity的四種launchMode
【Android】Activity的四種launchMode
【Android】Activity的四種launchMode
【Android】Activity的四種launchMode
【Android】Activity的四種launchMode
【Android】Activity的四種launchMode
【Android】Activity的四種launchMode

在圖中的下半部分是secondactivity跳轉到firstactivity後的棧結構變化的結果,我們注意到,secondactivity消失了,沒錯,在這個跳轉過程中系統發現有存在的firstactivity執行個體,于是不再生成新的執行個體,而是将firstactivity之上的activity執行個體統統出棧,将firstactivity變為棧頂對象,顯示到幕前。也許朋友們有疑問,如果将secondactivity也設定為singletask模式,那麼secondactivity執行個體是不是可以唯一呢?在我們這個示例中是不可能的,因為每次從secondactivity跳轉到firstactivity時,secondactivity執行個體都被迫出棧,下次等firstactivity跳轉到secondactivity時,找不到存在的secondactivity執行個體,于是必須生成新的執行個體。但是如果我們有thirdactivity,讓secondactivity和thirdactivity互相跳轉,那麼secondactivity執行個體就可以保證唯一。

這就是singletask模式,如果發現有對應的activity執行個體,則使此activity執行個體之上的其他activity執行個體統統出棧,使此activity執行個體成為棧頂對象,顯示到幕前。

這種啟動模式比較特殊,因為它會啟用一個新的棧結構,将acitvity放置于這個新的棧結構中,并保證不再有其他activity執行個體進入。

我們修改firstactivity的launchmode="standard",secondactivity的launchmode="singleinstance",由于涉及到了多個棧結構,我們需要在每個activity中顯示目前棧結構的id,是以我們為每個activity添加如下代碼:

【Android】Activity的四種launchMode
【Android】Activity的四種launchMode

我們看到從firstactivity跳轉到secondactivity時,重新啟用了一個新的棧結構,來放置secondactivity執行個體,然後按下後退鍵,再次回到原始棧結構;圖中下半部分顯示的在secondactivity中再次跳轉到firstactivity,這個時候系統會在原始棧結構中生成一個firstactivity執行個體,然後回退兩次,注意,并沒有退出,而是回到了secondactivity,為什麼呢?是因為從secondactivity跳轉到firstactivity的時候,我們的起點變成了secondactivity執行個體所在的棧結構,這樣一來,我們需要“回歸”到這個棧結構。

如果我們修改firstactivity的launchmode值為singletop、singletask、singleinstance中的任意一個,流程将會如圖所示:

【Android】Activity的四種launchMode
【Android】Activity的四種launchMode

singleinstance啟動模式可能是最複雜的一種模式,為了幫助大家了解,我舉一個例子,假如我們有一個share應用,其中的shareactivity是入口activity,也是可供其他應用調用的activity,我們把這個activity的啟動模式設定為singleinstance,然後在其他應用中調用。我們編輯shareactivity的配置:

然後我們在其他應用中這樣啟動該activity:

當我們打開shareactivity後再按後退鍵回到原來界面時,shareactivity做為一個獨立的個體存在,如果這時我們打開share應用,無需建立新的shareactivity執行個體即可看到結果,因為系統會自動查找,存在則直接利用。大家可以在shareactivity中列印一下taskid,看看效果。關于這個過程,原理圖如下:

【Android】Activity的四種launchMode
【Android】Activity的四種launchMode