Android的任务栈以及应用场景
首先介紹一下任務棧:
(1)程序打開時就創建了一個任務棧, 用于存儲當前程序的activity,所有的activity屬于一個任務棧。?
(2)一個任務棧包含了一個activity的集合, 去有序的選擇哪一個activity和用戶進行交互:只有在任務棧棧頂的activity才可以跟用戶進行交互。?
(3)任務棧可以移動到后臺, 并且保留了每一個activity的狀態. 并且有序的給用戶列出它們的任務, 而且還不丟失它們狀態信息。?
(4)退出應用程序時:當把所有的任務棧中所有的activity清除出棧時,任務棧會被銷毀,程序退出。
任務棧的缺點:?
(1)每開啟一次頁面都會在任務棧中添加一個Activity,而只有任務棧中的Activity全部清除出棧時,任務棧被銷毀,程序才會退出,這樣就造成了用,戶體驗差, 需要點擊多次返回才可以把程序退出了。?
(2)每開啟一次頁面都會在任務棧中添加一個Activity還會造成數據冗余, 重復數據太多, 會導致內存溢出的問題(OOM)。
為了解決任務棧的缺點,我們引入了啟動模式。
啟動模式(launchMode)在多個Activity跳轉的過程中扮演著重要的角色,它可以決定是否生成新的Activity實例,是否重用已存在的Activity實例,是否和其他Activity實例公用一個task里。這里簡單介紹一下task的概念,task是一個具有棧結構的對象,一個task可以管理多個Activity,啟動一個應用,也就創建一個與之對應的task。
Activity一共有以下四種launchMode:
- standard
- singleTop
- singleTask
- singleInstance
如何配置Activity的啟動模式??
直接在AndroidManifest.xml配置的android:launchMode屬性為以上四種之一即可。
1、standard?
standard模式是默認的啟動模式,不用為配置android:launchMode屬性即可,當然也可以指定值為standard。
stardard模式的原理如下:
如圖所示,每次跳轉系統都會在task中生成一個新的MainActivity實例,并且放于棧結構的頂部,當我們按下后退鍵時,才能看到原來的MainActivity實例。?
這就是standard啟動模式,不管有沒有已存在的實例,都生成新的實例。
2、singleTop
我們在上面的基礎上為指定屬性android:launchMode=”singleTop”,系統就會按照singleTop啟動模式處理跳轉行為。我們重復上面幾個動作,將會出現下面的現象:
我們看到這個結果跟standard有所不同,三個序列號是相同的,也就是說使用的都是同一個MainActivity實例;如果按一下后退鍵,程序立即退出,說明當前棧結構中只有一個Activity實例。singleTop模式的原理如下圖所示:
正如上圖所示,跳轉時系統會先在棧結構中尋找是否有一個MainActivity實例正位于棧頂,如果有則不再生成新的,而是直接使用。也許朋友們會有疑問,我只看到棧內只有一個Activity,如果是多個Activity怎么辦,如果不是在棧頂會如何?
這時候,FirstActivity會跳轉到SecondActivity,SecondActivity又會跳轉到FirstActivity。
我們看到,兩個MainActivity的序列號是不同的,證明從SecondActivity跳轉到MainActivity時生成了新的MainActivity實例。原理圖如下:
我們看到,當從SecondActivity跳轉到MainActivity時,系統發現存在有FirstActivity實例,但不是位于棧頂,于是重新生成一個實例。?
這就是singleTop啟動模式,如果發現有對應的Activity實例正位于棧頂,則重復利用,不再生成新的實例。
這種啟動模式通常適用于接受到消息后顯示的界面,例如QQ接受到消息后彈出Activity,如果一次來10條消息,總不能一次彈10個Activity。
3、singleTask ?在上面的基礎上我們修改MainActivity的屬性android:launchMode=”singleTask”
我們注意到,在上面的過程中,MainActivity的序列號是不變的,SecondActivity的序列號卻不是唯一的,說明從SecondActivity跳轉到MainActivity時,沒有生成新的實例,但是從MainActivity跳轉到SecondActivity時生成了新的實例。
SecondActivity跳轉到MainActivity后的棧結構變化的結果,我們注意到,SecondActivity消失了,沒錯,在這個跳轉過程中系統發現有存在的FirstActivity實例,于是不再生成新的實例,而是將MainActivity之上的Activity實例統統出棧,將MainActivity變為棧頂對象,顯示到幕前。也許朋友們有疑問,如果將SecondActivity也設置為singleTask模式,那么SecondActivity實例是不是可以唯一呢?在我們這個示例中是不可能的,因為每次從SecondActivity跳轉到MainActivity時,SecondActivity實例都被迫出棧,下次等MainActivity跳轉到SecondActivity時,找不到存在的SecondActivity實例,于是必須生成新的實例。但是如果我們有ThirdActivity,讓SecondActivity和ThirdActivity互相跳轉,那么SecondActivity實例就可以保證唯一。?
這就是singleTask模式,如果發現有對應的Activity實例,則使此Activity實例之上的其他Activity實例統統出棧,使此Activity實例成為棧頂對象,顯示到幕前。
4、singleInstance?
這種啟動模式比較特殊,因為它會啟用一個新的棧結構,將Activity放置于這個新的棧結構中,并保證不再有其他Activity實例進入。?
我們修改MainActivity的launchMode=”standard”
我們發現這兩個Activity實例分別被放置在不同的棧結構中,關于singleInstance的原理圖如下
我們看到從MainActivity跳轉到SecondActivity時,重新啟用了一個新的棧結構,來放置SecondActivity實例,然后按下后退鍵,再次回到原始棧結構;圖中下半部分顯示的在SecondActivity中再次跳轉到MainActivity,這個時候系統會在原始棧結構中生成一個MainActivity實例,然后回退兩次,注意,并沒有退出,而是回到了SecondActivity,為什么呢?是因為從SecondActivity跳轉到MainActivity的時候,我們的起點變成了SecondActivity實例所在的棧結構,這樣一來,我們需要“回歸”到這個棧結構。
應用場景:?
singleTop適合接收通知啟動的內容顯示頁面。例如,某個新聞客戶端的新聞內容頁面,如果收到10個新聞推送,每次都打開一個新聞內容頁面是很煩人的。
singleTask適合作為程序入口點。例如瀏覽器的主界面。不管從多少個應用啟動瀏覽器,只會啟動主界面一次,其余情況都會走onNewIntent,并且會清空主界面上面的其他頁面。之前打開過的頁面,打開之前的頁面就ok,不再新建。
singleInstance適合需要與程序分離開的頁面。例如鬧鈴提醒,將鬧鈴提醒與鬧鈴設置分離。singleInstance不要用于中間頁面,如果用于中間頁面,跳轉會有問題,比如:A -> B (singleInstance) -> C,完全退出后,在此啟動,首先打開的是B。
總結
以上是生活随笔為你收集整理的Android的任务栈以及应用场景的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: enfuzion与lsf构建渲染集群_渲
- 下一篇: 追忆第一次南下深圳有哪些重大抉择(上)?