启动模式 和 任务栈
1. LaunchMode
再簡單的東西也需要認(rèn)真對(duì)待。
Activity的四中啟動(dòng)模式:
首先是 standard ,這是系統(tǒng)默認(rèn)的啟動(dòng)模式。
當(dāng)我們啟動(dòng)新的Activity時(shí)候,是調(diào)用 Context 的startActivity() 方法。
但是,如果這個(gè)Context不是Activity類型而是ApplicationContext。那這時(shí)候會(huì)報(bào)錯(cuò),無法啟動(dòng)。因?yàn)樵趕tandard模式下,是在當(dāng)前Activity的所屬任務(wù)棧中啟動(dòng)新的Activity,如果這個(gè)Context不是Activity類型的話,那么就不存在所謂的Activity任務(wù)棧了,報(bào)錯(cuò)也就理所當(dāng)然了。所以這個(gè)時(shí)候可以配置 Flag (FLAG_ACTIVITY_NEW_TASK),這時(shí)候?qū)嶋H上以singleTask模式啟動(dòng)。在新的任務(wù)棧中啟動(dòng)Activity。這樣,就可以使用ApplicationContext啟動(dòng)Activity。?乛?乛?
再看singleTop,如果這個(gè)Activity已經(jīng)存在于這個(gè)棧的棧頂,那么就會(huì)復(fù)用這個(gè)Activity,不會(huì)重新創(chuàng)建新的Activity。這個(gè)時(shí)候Activity 的onCreate() 和 onStart() 不會(huì)被調(diào)用。但是會(huì)有另一個(gè)方法 onNewIntent() 方法被調(diào)用。當(dāng)配置了singleTop的Activity處于棧頂,又再次被啟動(dòng)的時(shí)候,調(diào)用如下:
然后是singleTask 棧內(nèi)復(fù)用。這種模式下,只要Activity在 某一個(gè)棧內(nèi)(可能存在多個(gè)棧) 存在,就回復(fù)用這個(gè)Activity,而不會(huì)去重新創(chuàng)建。和singleTop一樣,系統(tǒng)也會(huì)調(diào)用 onNewIntent() 方法。
這里有幾種情況,首先是請(qǐng)求的棧是本棧還是一個(gè)新棧,還有就是Activity存不存在。
現(xiàn)在有個(gè)Activity棧,有ABC三個(gè)Activity。要?jiǎng)?chuàng)建一個(gè)新的Activity D。
1. 本Activity棧 — Activity不存在
這種情況最簡單,創(chuàng)建一個(gè)新的Activity,壓入棧中即可。這個(gè)棧變成了 ABCD。
2. 本Activity棧 — Activity存在
這是如果本棧的Activity 是 ADBC 這個(gè)樣子。然后再使用singleTask模式啟動(dòng) D 這個(gè)Activity。系統(tǒng)會(huì)將D 調(diào)到棧頂,并且調(diào)用D的 onNewIntent() 方法。同時(shí)會(huì)將D上面的所有Activity清除掉。這時(shí)棧變成了 AD。
3. 新Activity棧 — Activity不存在
這個(gè)時(shí)候需要重新創(chuàng)建因?yàn)檫@個(gè)棧不存在,這個(gè)Activity也存在,所以這時(shí),系統(tǒng)先創(chuàng)建一個(gè)棧,然后再創(chuàng)建一個(gè)Activity,再將Activity壓入新棧中。
4. 新Activity棧 — Activity存在
這是最復(fù)雜一種情況。這時(shí)候會(huì)有一個(gè) 后臺(tái)棧 和 前臺(tái)棧 的概念。
先來分析這種情況,當(dāng)前Activity肯定處于前臺(tái)棧,既然新的Activity要在新的棧中啟動(dòng),并且Activity已經(jīng)存在,那么,這個(gè)??隙ㄒ呀?jīng)創(chuàng)建完成,并且屬于 后臺(tái)棧 。這時(shí),系統(tǒng)會(huì)先將整個(gè)任務(wù)棧調(diào)到前臺(tái),然后再按照singleTask 原則,該復(fù)用復(fù)用,該清除清除。這時(shí)整個(gè)棧中的所有Activity都會(huì)被調(diào)到另一個(gè)棧之前。所以,一直按Back鍵,回退的Activity順序會(huì)有所改變。
最后是 singleInstance 。一種加強(qiáng)型的singleTask。擁有singleTask的所有特性。不同在于,這個(gè)模式的Activity會(huì)在一個(gè)新的獨(dú)特的棧中創(chuàng)建Activity,這個(gè)棧中只有這個(gè)Activity存在。由于棧內(nèi)復(fù)用的特性,所有的這個(gè)Activity啟動(dòng)時(shí)都不會(huì)重新創(chuàng)建。除非這個(gè)獨(dú)特的任務(wù)棧被系統(tǒng)殺死。
2. 任務(wù)棧
這里主要說明兩個(gè)配置參數(shù) taskAffinity 和 allowTaskReparenting 。
taskAffinity:每個(gè)Activity都有 taskAffinity 屬性,這個(gè)屬性指出了它希望進(jìn)入的Task。默認(rèn)情況下,taskAffinity 的值是包名。所以如果你設(shè)置了這個(gè)屬性是包名的話,那和沒設(shè)置是一樣的。
<activity android:name=".Act3" android:taskAffinity="com.mytest.task2"/>如果想要Activity在新的任務(wù)棧中啟動(dòng),那么需要兩步:
在Activity中可以使用 Activity. getTaskId() 方法來獲取當(dāng)前Task的 ID。驗(yàn)證自己的猜想。
allowTaskReparenting :這個(gè)屬性用于設(shè)定Activity能夠從啟動(dòng)它的任務(wù)中轉(zhuǎn)移到另一個(gè)與啟動(dòng)它的任務(wù)有親緣關(guān)系的任務(wù)中。
這個(gè)親緣關(guān)系只能和根Activity去比較,所以必須在根Activity設(shè)置taskAffinity,而需要轉(zhuǎn)移的Activity不需要是根Activity。
如果設(shè)置了true,則能夠轉(zhuǎn)移,如果設(shè)置了false,則這個(gè)Activity保留在啟動(dòng)它的那個(gè)任務(wù)中。
設(shè)置方式:
這里比較難理解,舉個(gè)例子吧:
現(xiàn)在有兩個(gè)應(yīng)用 應(yīng)用A、 應(yīng)用B 。
應(yīng)用A 是在前臺(tái)的應(yīng)用,應(yīng)用B是后臺(tái)應(yīng)用。
應(yīng)用B 的 Act 1 和 Act 2 有相同的taskAffinity。(這樣就具有了親緣關(guān)系)
應(yīng)用B 的 Act 2 配置了android:allowTaskReparenting="true" 。
現(xiàn)在 應(yīng)用A 啟動(dòng)應(yīng)用B 的 Act 2。
然后回到桌面,啟動(dòng)應(yīng)用B 的 Act 1。
流程如下:
其中,Act 2 這個(gè)Activity從應(yīng)用A的棧中,轉(zhuǎn)移到了應(yīng)用B的棧的頂端。
(可以將應(yīng)用B 的 Act 2想象成瀏覽器的網(wǎng)頁界面。其他應(yīng)用打開了網(wǎng)頁。這時(shí)打開瀏覽器應(yīng)用,那個(gè)打開的網(wǎng)頁處于最前端)
總結(jié)
以上是生活随笔為你收集整理的启动模式 和 任务栈的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: include、ViewStub、mer
- 下一篇: ios 中的基本算数函数