Activity四種啟動模式與任務棧(Task)總結分析
最近在總結android基礎問題 比如Activity的四種啟動模式 其中有涉及到任務棧的問題 之前都是一知半解 現在想著用筆記錄下來 可供自己以後參考
android任務棧簡單瞭解
1. android任務棧又稱為Task,它是一個棧結構,具有後進先出的特性,用於存放我們的Activity元件。
2. 我們每次開啟一個新的Activity或者退出當前Activity都會在一個稱為任務棧的結構中新增或者減少一個Activity元件,因此一個任務棧包含了一個activity的集合, android系統可以通過Task有序地管理每個activity,並決定哪個Activity與使用者進行互動:只有在任務棧棧頂的activity才可以跟使用者進行互動。
3.
4. 需要注意的是,一個App中可能不止一個任務棧,某些特殊情況下,單獨一個Actvity可以獨享一個任務棧。還有一點就是一個Task中的Actvity可以來自不同的App,同一個App的Activity也可能不在一個Task中。
簡單瞭解任務棧之後 我們來看一下Activity的四種啟動模式
Activity的啟動模式
為什麼需要Activity的啟動模式?
開發專案過程中,需要在本應用(本專案中)多個Activity跳轉,也可能需要在本應用中開啟其它應用的可複用的Activity。如我們可能需要跳轉到原來某個Activity例項,此時我們更希望這個Activity可以被重用而不是建立一個新的 Activity,但根據Android系統的預設行為,當我們多次啟動同一個Activity時,系統會建立多個例項,並把它們按照先進後出的原則一一放入任務棧中,當我們按back鍵時,就會有一個activity從任務棧頂移除,重複下去,直到任務棧為空,系統就會回收這個任務棧。但是這樣以來,系統多次啟動同一個Activity時就會重複建立多個例項,這種做法顯然不合理,為了能夠優化這個問題,Android提供四種啟動模式來修改系統這一預設行為。
目前啟動模式有四種,分別是standard,singleTop,singTask和singleInstance,接下來我們將分別介紹這四種模式
預設模式 Standard
Activity 預設啟動模式就是Standard 模式,無需指定、配置。使用該模式啟動Activity,每次啟動一個Activity都會重寫建立一個新的例項,不管這個例項存不存在,這種模式下,誰啟動了該模式的Activity,該Activity就屬於啟動它的Activity的任務棧中。這個Activity它的onCreate(),onStart(),onResume()方法都會被呼叫。
配置形式:
<activity android:name=".standard.StandardActivity" android:launchMode="standard" >
預設模式 可以不用進行配置 即 android:launchMode = “standard” 可以刪除
使用場景:
什麼時候用standard模式呢?standartd模式是activity的預設模式,大部分情況下,都應該使用這種模式,也就是在配置檔案中什麼都不用做,當確實有特殊需求時,再考慮其他模式。
棧頂複用模式 SingleTop
假如設定為該模式的Activity已經位於棧頂則不會重複建立 ,同時它的onNewIntent方法會被呼叫,onCreate(),onStart()方法不會被呼叫,如果棧頂不存在該Activity的例項,則情況與standard模式相同。
配置形式:
<activity android:name=".singletop.SingleTopActivity" android:launchMode="singleTop">
singleTop模式分3種情況
- 當前棧中已有該Activity的例項並且該例項位於棧頂時,不會新建例項,而是複用棧頂的例項,並且會將Intent物件傳入,回撥onNewIntent方法
- 當前棧中已有該Activity的例項但是該例項不在棧頂時,其行為和standard啟動模式一樣,依然會建立一個新的例項
- 當前棧中不存在該Activity的例項時,其行為同standard啟動模式
standard和singleTop啟動模式都是在原任務棧中新建Activity例項,不會啟動新的Task,即使你指定了taskAffinity屬性。
那麼什麼是taskAffinity屬性呢,可以簡單的理解為任務相關性。
- 這個引數標識了一個Activity所需任務棧的名字,預設情況下,所有Activity所需的任務棧的名字為應用的包名
- 我們可以單獨指定每一個Activity的taskAffinity屬性覆蓋預設值
- 一個任務的affinity決定於這個任務的根activity(root activity)的taskAffinity
- 在概念上,具有相同的affinity的activity(即設定了相同taskAffinity屬性的activity)屬於同一個任務
- 為一個activity的taskAffinity設定一個空字串,表明這個activity不屬於任何task
很重要的一點taskAffinity屬性不對standard和singleTop模式有任何影響,即時你指定了該屬性為其他不同的值,這兩種啟動模式下不會建立新的task(如果不指定即預設值,即包名)
使用場景:
通知欄點選後需要啟動一個活動,這個就要用到這個模式,否則的話每次點選都會新建一個活動
棧內複用模式 SingleTask
這個模式十分複雜,有各式各樣的組合。在這個模式下,如果棧中存在這個Activity的例項就會複用這個Activity,不管它是否位於棧頂,複用時,會將它上面的Activity全部出棧,並且會回撥該例項的onNewIntent方法。其實這個過程還存在一個任務棧的匹配,因為這個模式啟動時,會在自己需要的任務棧中尋找例項,這個任務棧就是通過taskAffinity屬性指定。如果這個任務棧不存在,則會建立這個任務棧。
配置形式:
<activity android:name=".singleTask.SingleTaskActivity" android:launchMode="singleTask" >
使用場景:
App的首頁一般設定啟動模式為:SingleTask模式 保證單例
<activity
android:name=".view.activity.MainActivity"
android:launchMode="singleTask" />
我們是否設定Activity為singleTask模式,就是看我們activity是否需要單例,例如你的某個Activity裡面有一個列表,如果有多個例項,有可能導致使用者看到的列表不一致,有的Activity需要經常啟動,如果每次都建立例項,會導致佔用資源過多,這些情況都可以使用singleTask模式,但啟動singleTask模式的Activity會導致任務棧內它上面的Activity被銷燬,有可能會影響使用者體驗,使用時要注意
一般在專案中 我們會這是首頁 HomeActivity啟動模式為SingleTask模式
全域性唯一模式 singleInstance
該模式具備singleTask模式的所有特性外,與它的區別就是,這種模式下的Activity會單獨佔用一個Task棧,具有全域性唯一性,即整個系統中就這麼一個例項,由於棧內複用的特性,後續的請求均不會建立新的Activity例項,除非這個特殊的任務棧被銷燬了。以singleInstance模式啟動的Activity在整個系統中是單例的,如果在啟動這樣的Activiyt時,已經存在了一個例項,那麼會把它所在的任務排程到前臺,重用這個例項。
配置形式:
<activity android:name=".singleinstance.SingleInstanceActivity" android:launchMode="singleInstance" >
使用場景:
singleInstance模式也是單例的,但和singleTask不同,singleTask只是任務棧內單例,系統裡是可以有多個singleTask Activity例項的,而singleInstance Activity在整個系統裡只有一個例項,啟動一singleInstanceActivity時,系統會建立一個新的任務棧,並且這個任務棧只有他一個Activity。
SingleInstance模式並不常用,如果我們把一個Activity設定為singleInstance模式,你會發現它啟動時會慢一些,切換效果不好,影響使用者體驗。它往往用於多個應用之間,例如一個電視launcher裡的Activity,通過遙控器某個鍵在任何情況可以啟動,這個Activity就可以設定為singleInstance模式,當在某應用中按鍵啟動這個Activity,處理完後按返回鍵,就會回到之前啟動它的應用,不影響使用者體驗。
想要真的理解四種啟動模式需要卡發者自己去設定執行 這樣可以最好的進行理解,變成自己的東西;
參考: