Android 基础 —— 活动的启动模式
活動的啟動模式來說應該是個全新的概念,在實際項目中我們應該根據特定的需求為每個活動指定恰當的啟動模式。啟動模式一共有四種,分別是standard、singleTop、singleTask 和singleInstance , 可以在AndroidManifest.xml 中通過給<activity> 標簽指定Android:launchMode屬性來選擇啟動模式。
Standard:標準模式.默認啟動模式,在不顯式指定的情況下,所有的活動都是使用這種模式,每次都會創建新的活動實例
SingleTop:棧頂復用模式。在啟動活動時如果發現返回棧的棧頂已經是該活動,則可以認為直接使用它,不再創建新的活動實例
如果啟動的活動處于任務棧中但不處于棧頂,這個時候會重新創建該活動實例
SingleTask:棧內復用模式。每次啟動活動的時候都會檢查返回棧中該活動是否已經存在,若不存在則創建新的活動實例,若存在則直接使用該活動,并且處于該活動之上的活動實例全部出棧
SingleInstance:單實例模式。若一個活動指定為該啟動模式,則會創建一個新的任務棧來管理此活動(好處是方便別的應用程序可以調用我們這個活動),當別的應用程序調用此活動時不必再重新創建該活動實例
?
下面我們來分別學習:
一、?standard(標準啟動模式)
?????????standard 是活動默認的啟動模式,在不進行顯式指定的情況下,所有活動都會自動使用這種啟動模式。因此,到目前為止我們寫過的所有活動都是使用的standard 模式。經過上一節的學習,你已經知道了Android 是使用返回棧來管理活動的,在standard 模式(即默認情況)下,每當啟動一個新的活動,它就會在返回棧中入棧,并處于棧頂的位置。對于使用standard 模式的活動,系統不會在乎這個活動是否已經在返回棧中存在,每次啟動都會創建該活動的一個新的實例。
???????? 我們現在通過實踐來體會一下standard 模式,修改FirstActivity 中onCreate()方法的代碼,如下所示:
[java]?view plaincopy代碼看起來有些奇怪吧,在MainActivity 的基礎上啟動MainActivity。從邏輯上來講這確實沒什么意義,不過我們的重點在于研究standard 模式,因此不必在意這段代碼有什么實際用途。另外我們還在onCreate()方法中添加了一行打印信息,用于打印當前活動的實例。
現在重新運行程序,然后在MainActivity 界面連續點擊兩次按鈕,可以看到LogCat 中打印信息
?
????? 從打印信息中我們就可以看出,每點擊一次按鈕就會創建出一個新的MainActivity 實例。此時返回棧中也會存在三個MainActivity的實例,因此你需要連按三次Back鍵才能退出程序。
standard 模式的原理示意圖,如圖所示
?
?
二、?singleTop(棧頂復用模式)
?????? 可能在有些情況下,你會覺得standard 模式不太合理。活動明明已經在棧頂了,為什么再次啟動的時候還要創建一個新的活動實例呢?別著急,這只是系統默認的一種啟動模式而已,你完全可以根據自己的需要進行修改,比如說使用singleTop 模式。當活動的啟動模式指定為singleTop,在啟動活動時如果發現返回棧的棧頂已經是該活動,則認為可以直接使用它,不會再創建新的活動實例。
我們還是通過實踐來體會一下,修改AndroidManifest.xml 中MainActivity 的啟動模式,如下所示:
[java]?view plaincopy然后重運行程序,查看LogCat 會看到已經創建了一個MainActivity 的實例,如圖所示。
但是之后不管你點擊多少次按鈕都不會再有新的打印信息出現,因為目前MainActivity已經處于返回棧的棧頂,每當想要再啟動一個MainActivity 時都會直接使用棧頂的活動,因此MainActivity 也只會有一個實例,僅按一次Back 鍵就可以退出程序。
不過當MainActivity 并未處于棧頂位置時,這時再啟動MainActivity,還是會創建新的實例的。下面我們來實驗一下,在MainActivity 中添加第二個按鈕onCreate()方法的代碼,如下所示:
[java]?view plaincopy按鈕功能是跳轉到第二個界面,下面修改SecondActivity
[java]?view plaincopy我們在SecondActivity 中的按鈕點擊事件里又加入了啟動MainActivity 的代碼。現在重新運行程序,在MainActivity 界面點擊按鈕進入到SecondActivity,然后在SecondActivity 界面點擊按鈕,又會重新進入到MainActivity。查看LogCat 中的打印信息,如圖所示
可以看到系統創建了兩個不同的MainActivity 實例,這是由于在SecondActivity 中再次啟動MainActivity 時,棧頂活動已經變成了SecondActivity,因此會創建一個新的MainActivity實例。現在按下Back 鍵會返回到SecondActivity,再次按下Back 鍵又會回到FirstActivity,再按一次Back 鍵才會退出程序。
singleTop 模式的原理示意圖,如圖2.34 所示。
?
?
三、singleTask
??????? 使用singleTop 模式可以很好地解決重復創建棧頂活動的問題,但是正如你在上一節所看到的,如果該活動并沒有處于棧頂的位置,還是可能會創建多個活動實例的。那么有沒有什么辦法可以讓某個活動在整個應用程序的上下文中只存在一個實例呢?這就要借助singleTask 模式來實現了。當活動的啟動模式指定為singleTask,每次啟動該活動時系統首先會在返回棧中檢查是否存在該活動的實例,如果發現已經存在則直接使用該實例,并把在這個活動之上的所有活動統統出棧,如果沒有發現就會創建一個新的活動實例。
??????? 由于其和singleTop類似,這里不再詳細介紹其特點。singleTask 模式的原理示意圖:
?
?
四、?singleInstance
?????????singleInstance 模式應該算是四種啟動模式中最特殊也最復雜的一個了,你也需要多花點功夫來理解這個模式。不同于以上三種啟動模式,指定為singleInstance 模式的活動會啟用一個新的返回棧來管理這個活動(其實如果singleTask 模式指定了不同的taskAffinity,也會啟動一個新的返回棧)。那么這樣做有什么意義呢?想象以下場景,假設我們的程序中有一個活動是允許其他程序調用的,如果我們想實現其他程序和我們的程序可以共享這個活動的實例,應該如何實現呢?使用前面三種啟動模式肯定是做不到的,因為每個應用程序都會有自己的返回棧,同一個活動在不同的返回棧中入棧時必然是創建了新的實例。而使用singleInstance 模式就可以解決這個問題,在這種模式下會有一個單獨的返回棧來管理這個活動,不管是哪個應用程序來訪問這個活動,都共用的同一個返回棧,也就解決了共享活動實例的問題。
??????? 修改AndroidManifest.xml 中SecondActivity 的啟動模式:
[java]?view plaincopy修改MainActivity 中onCreate()方法的代碼:
[java]?view plaincopy修改SecondActivity 中onCreate()方法的代碼:
[java]?view plaincopy修改ThirdActivity 中onCreate()方法的代碼:
[java]?view plaincopy仍然是在onCreate()方法中打印了當前返回棧的id。現在重新運行程序,在MainActivity界面點擊按鈕進入到SecondActivity ,然后在SecondActivity 界面點擊按鈕進入到ThirdActivity。查看LogCat 中的打印信息,如圖所示
????? 可以看到, SecondActivity 的Task id 不同于MainActivity 和ThirdActivity , 這說明SecondActivity 確實是存放在一個單獨的返回棧里的,而且這個棧中只有SecondActivity 這一個活動。
?????然后我們按下Back 鍵進行返回,你會發現ThirdActivity 竟然直接返回到了MainActivity,再按下Back 鍵又會返回到SecondActivity,再按下Back 鍵才會退出程序,這是為什么呢?其實原理很簡單,由于FirstActivity 和ThirdActivity 是存放在同一個返回棧里的,當在ThirdActivity 的界面按下Back 鍵,ThirdActivity 會從返回棧中出棧,那么MainActivity 就成為了棧頂活動顯示在界面上,因此也就出現了ThirdActivity 直接返回到MainActivity 的情況。然后在MainActivity 界面再次按下Back 鍵,這時當前的返回棧已經空了,于是就顯示了另一個返回棧的棧頂活動,即SecondActivity。最后再次按下Back 鍵,這時所有返回棧都已經空了,也就自然退出了程序。
singleInstance 模式的原理示意圖
總結
以上是生活随笔為你收集整理的Android 基础 —— 活动的启动模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS——Core Animation
- 下一篇: Android性能优化典范(转)