在使用編寫界面時爵川,我們可能從來沒有關(guān)注過Activity的啟動模式敷鸦,其實默認(rèn)的啟動模式為標(biāo)準(zhǔn)的啟動模式(standard);在Activity任務(wù)棧中寝贡,標(biāo)準(zhǔn)的啟動模式會為每一個Activity創(chuàng)建一個實例轧膘,其實在很多需求中,這樣的使用明顯是不準(zhǔn)確的兔甘,我們應(yīng)該盡可能的將每個Activity的啟動模式設(shè)置正確以便程序更加健壯谎碍。
四大啟動模式如下:
standard
singleTop
singleTask
singleInstance
下面我們看看官方對啟動模式的解釋:
啟動模式 | 用例 | 多個實例? | 解釋 |
---|---|---|---|
standard | 大多數(shù) Activity 的正常啟動 | 是 | 默認(rèn)值洞焙。系統(tǒng)始終會在目標(biāo)任務(wù)中創(chuàng)建新的 Activity 實例并向其傳送 Intent蟆淀。 |
singleTop | 大多數(shù) Activity 的正常啟動 | 有條件 | 如果目標(biāo)任務(wù)的頂部已存在一個 Activity 實例,則系統(tǒng)會通過調(diào)用該實例的 onNewIntent()方法向其傳送 Intent澡匪,而不是創(chuàng)建新的 Activity 實例熔任。 |
singleTask | 專用啟動(不建議用作常規(guī)用途) | 否 | 系統(tǒng)在新任務(wù)的根位置創(chuàng)建 Activity 并向其傳送 Intent。 不過唁情,如果已存在一個 Activity 實例疑苔,則系統(tǒng)會通過調(diào)用該實例的 onNewIntent()方法向其傳送 Intent,而不是創(chuàng)建新的 Activity 實例甸鸟。 |
singleInstance | 專用啟動(不建議用作常規(guī)用途) | 否 | 與“singleTask"”相同惦费,只是系統(tǒng)不會將任何其他 Activity 啟動到包含實例的任務(wù)中。 該 Activity 始終是其任務(wù)唯一僅有的成員抢韭。 |
看到上面的的解釋是否都明白呢薪贫?下面我們使用一個例子來說明一下使用方法, 創(chuàng)建了四個Activity刻恭,分別使用Standard瞧省、SingleTop、SingleTask鳍贾、SingleInstance 啟動模式鞍匾, 并且SingleTask作為程序的啟動Activity:
每個Activity都是同樣的代碼,獲取到當(dāng)前Task任務(wù)棧中的Activity數(shù)量以及跳轉(zhuǎn)到每個Activity的點擊事件:
class SingleTaskActivity : AppCompatActivity() {
val TAG = "ActivityManagerDemo"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_single_task)
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
fun getActivityStack(view: View) {
var activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
var appTasks = activityManager.appTasks
for (appTask in appTasks) {
val taskInfo = appTask.taskInfo
Log.d(TAG, taskInfo.numActivities.toString())
}
}
fun standard(view: View) {
// 跳轉(zhuǎn)到標(biāo)準(zhǔn)
startActivity(Intent(this@SingleTaskActivity, StandardActivity::class.java))
}
fun singleInstance(view: View) {
// 單例
startActivity(Intent(this@SingleTaskActivity, SingleInstanceActivity::class.java))
}
fun singleTop(view: View) {
// 棧頂
startActivity(Intent(this@SingleTaskActivity, SingleTopActivity::class.java))
}
fun singleTask(view: View) {
// 去除棧上
startActivity(Intent(this@SingleTaskActivity, SingleTaskActivity::class.java))
}
}
為了方便我們查看骑科,將Standard頁面設(shè)置為 1 橡淑, SingleTop 設(shè)置為 2 ,SingleTask 設(shè)置為 3纵散, SingleInstance設(shè)置為 4梳码;接下來測試Standard啟動模式隐圾,程序開始進(jìn)入到SingleTaskActivity。
Standard 模式測試
按照 3 -> 1 -> 1-> 1->1 測試
09-29 09:15:27.036 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:1 棧id為:26
09-29 09:15:31.752 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:2 棧id為:26
09-29 09:15:33.486 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:3 棧id為:26
09-29 09:15:35.267 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:4 棧id為:26
09-29 09:15:37.236 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:5 棧id為:26
可以看到掰茶,每次跳轉(zhuǎn)都會生成一個StandardActivity實例暇藏!
SingleTop模式測試
按照 3 -> 1 -> 2-> 2 測試
09-29 09:16:10.076 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:1 棧id為:26
09-29 09:16:42.851 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:2 棧id為:26
09-29 09:16:46.896 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:3 棧id為:26
09-29 09:16:49.631 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:3 棧id為:26
在測試的時候,跳轉(zhuǎn)到2之后濒蒋,2已經(jīng)處于棧頂盐碱,再次點擊跳轉(zhuǎn)到SingleTop界面無變化,說明已經(jīng)復(fù)用了棧頂存在Activity沪伙。
SingleTask模式測試
按照 3 -> 1 -> 2-> 3 測試
09-29 09:18:27.561 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:1 棧id為:26
09-29 09:18:33.782 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:2 棧id為:26
09-29 09:18:40.754 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:3 棧id為:26
09-29 09:18:43.580 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:1 棧id為:26
當(dāng)兩個頁面跳轉(zhuǎn)完之后再次跳轉(zhuǎn)到SingleTask頁面瓮顽,獲取到棧內(nèi)的數(shù)量為1,說明了跳轉(zhuǎn)到SingleTask頁面的時候围橡,會將位于SingleTask棧上的所有頁面銷毀暖混。
SingleInstance模式測試
按照 3 -> 1 -> 2-> 4->1->1->4 測試
09-29 09:18:58.824 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:1 棧id為:26
09-29 09:19:06.654 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:2 棧id為:26
09-29 09:19:13.225 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:3 棧id為:26
09-29 09:19:17.038 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:1 棧id為:27
09-29 09:19:24.149 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:4 棧id為:26
09-29 09:19:28.156 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:5 棧id為:26
09-29 09:19:33.445 9208-9208/com.ellison.manager D/ActivityManagerDemo: 當(dāng)前任務(wù)棧中Activity數(shù)量為:1 棧id為:27
SingleInstance模式可能比較難理解,上面沒有說到棧id翁授,這是app給每個task設(shè)置的棧id拣播,一般一個應(yīng)用存在同一個棧中,所以id相同收擦,而SingleInstance模式在系統(tǒng)在只存在一個實例贮配,而且還會給Activity分配一個不同的任務(wù)棧,所以當(dāng)我們第一次跳轉(zhuǎn)到SingleInstance的Activity時塞赂,會為Activity創(chuàng)建一個新的棧id泪勒,等同于該Activity和其他Activity分隔開了,而后面我們再次回到Standard模式的Activity時宴猾,又回到了之前的任務(wù)棧圆存。
總結(jié)
面試首先說出Activity啟動模式,再結(jié)合實用場景鳍置,比如SIngleTask模式:現(xiàn)在許多的應(yīng)用都是使用Tab頁面加載Fragment辽剧,此時MainTabActivity就可以使用SingleTask模式送淆,因為當(dāng)使用多級頁面跳轉(zhuǎn)之后再回到MainTabActivity税产,此時在回退,會發(fā)現(xiàn)有多個MainTabActivity偷崩,這樣設(shè)計肯定是不合理的辟拷,使用SingleTask模式則很好的解決了這一問題。