Android中Activity四種啟動(dòng)模式和taskAffinity屬性詳解
Application,Task和Process
- Application是一組組件的集合
- task是一組相互關(guān)聯(lián)的activity的集合
task是可以跨應(yīng)用的笼呆,這正是task存在的一個(gè)重要原因梯皿。有的Activity揣云,雖然不在同一個(gè)app中妆绞,但為了保持用戶(hù)操作的連貫性板惑,把他們放在同一個(gè)任務(wù)中裆熙。例如端礼,在我們的應(yīng)用中的一個(gè)Activity A中點(diǎn)擊發(fā)送郵件,會(huì)啟動(dòng)郵件程序的一個(gè)Activity B來(lái)發(fā)送郵件入录,這兩個(gè)activity是存在于不同app中的蛤奥,但是被系統(tǒng)放在一個(gè)任務(wù)中,這樣當(dāng)發(fā)送完郵件后僚稿,用戶(hù)按back鍵返回凡桥,可以返回到原來(lái)的Activity A中,這樣就確保了用戶(hù)體驗(yàn)蚀同。 - 在默認(rèn)情況下缅刽,一個(gè)應(yīng)用程序的所有組件運(yùn)行在同一個(gè)進(jìn)程中。但是這種情況也有例外蠢络,即衰猛,應(yīng)用程序中的不同組件可以運(yùn)行在不同的進(jìn)程中。只需要在manifest中用process屬性指定組件所運(yùn)行的進(jìn)程的名字刹孔。
1. standard
每次都會(huì)實(shí)例化一個(gè)啡省。
2. singleTop
- 如果一個(gè)以singleTop模式啟動(dòng)的activity的實(shí)例已經(jīng)存在于任務(wù)桟的桟頂,那么再啟動(dòng)這個(gè)Activity時(shí)髓霞,不會(huì)創(chuàng)建新的實(shí)例卦睹,而是重用位于棧頂?shù)哪莻€(gè)實(shí)例,并且會(huì)調(diào)用該實(shí)例的onNewIntent()方法將Intent對(duì)象傳遞到這個(gè)實(shí)例中方库。
- 如果以singleTop模式啟動(dòng)的activity的一個(gè)實(shí)例已經(jīng)存在與任務(wù)桟中结序,但是不在桟頂,那么它的行為和standard模式相同纵潦,也會(huì)創(chuàng)建多個(gè)實(shí)例笼痹。
3. singleTask
把啟動(dòng)模式設(shè)置為singleTask,framework在啟動(dòng)該activity時(shí)只會(huì)把它標(biāo)示為可在一個(gè)新任務(wù)中啟動(dòng)(類(lèi)似FLAG_ACTIVITY_NEW_TASK)酪穿,至于是否在一個(gè)新任務(wù)中啟動(dòng)凳干,還要受其他條件的限制。
**taskAffinity**是manifest文件中<activity>的一個(gè)重要屬性
1. taskAffinity表示當(dāng)前activity具有親和力的一個(gè)任務(wù)被济,這個(gè)taskAffinity表示一個(gè)任務(wù)救赐,這個(gè)任務(wù)就是當(dāng)前activity所在的任務(wù)。
在概念上,具有相同的affinity的activity(即設(shè)置了相同taskAffinity屬性的activity)屬于同一個(gè)任務(wù)经磅。
2. 默認(rèn)情況下泌绣,**一個(gè)應(yīng)用中的所有activity具有相同的taskAffinity**,即應(yīng)用程序的包名预厌。我們可以通過(guò)設(shè)置不同的taskAffinity屬性給應(yīng)用中的activity分組阿迈,也可以把**不同的應(yīng)用中的activity的taskAffinity設(shè)置成相同的值**。
3. 為一個(gè)activity的taskAffinity設(shè)置一個(gè)空字符串轧叽,表明這個(gè)activity不屬于任何task苗沧。
**SecondActivity沒(méi)設(shè)置singleTask,設(shè)置taskAffinity的情況:**
a. 如果存在這樣的一個(gè)任務(wù)炭晒,則檢查在這個(gè)任務(wù)中是否已經(jīng)有了一個(gè)SecondActivity的實(shí)例待逞,如果已經(jīng)存在一個(gè)SecondActivity的實(shí)例,則會(huì)重用這個(gè)任務(wù)和任務(wù)中的SecondActivity實(shí)例网严,將這個(gè)任務(wù)調(diào)到前臺(tái)识樱,清除位于SecondActivity上面的所有Activity,顯示SecondActivity震束,并調(diào)用SecondActivity的onNewIntent()怜庸;
b.如果不存在一個(gè)SecondActivity的實(shí)例,會(huì)在這個(gè)任務(wù)中創(chuàng)建SecondActivity的實(shí)例垢村,并調(diào)用onCreate()方法
如果不存在這樣的一個(gè)任務(wù)割疾,會(huì)創(chuàng)建一個(gè)新的affinity為com.jg.zhang.androidtasktest.second的任務(wù),并且將SecondActivity啟動(dòng)到這個(gè)新的任務(wù)中.
**SecondActivity只設(shè)置啟動(dòng)模式為singleTask肝断,而不設(shè)置taskAffinity,即三個(gè)Activity的taskAffinity相同驰凛,都為應(yīng)用的包名胸懈,那么SecondActivity是不會(huì)開(kāi)啟一個(gè)新任務(wù)的**
1. 在MainActivity啟動(dòng)SecondActivity時(shí),發(fā)現(xiàn)啟動(dòng)模式為singleTask恰响,那么設(shè)定他的啟動(dòng)標(biāo)志為FLAG_ACTIVITY_NEW_TASK
2. 然后獲得SecondActivity的taskAffinity趣钱,即為包名com.jg.zhang.androidtasktest
3. 檢查是否已經(jīng)存在一個(gè)affinity為com.jg.zhang.androidtasktest的任務(wù),這個(gè)任務(wù)是存在的胚宦,就是MainActivity所在的任務(wù)首有,這個(gè)任務(wù)是在啟動(dòng)MainActivity時(shí)開(kāi)啟的
4. 既然已經(jīng)存在這個(gè)任務(wù),就檢索在這個(gè)任務(wù)中是否存在一個(gè)SecondActivity的實(shí)例枢劝,發(fā)現(xiàn)不存在
5.在這個(gè)已有的任務(wù)中啟動(dòng)一個(gè)SecondActivity的實(shí)例
**SecondActivity啟動(dòng)模式設(shè)為singleTask井联,并且taskAffinity設(shè)為com.jg.zhang.androidtasktest.second時(shí)的啟動(dòng)過(guò)程:
1. 在MainActivity啟動(dòng)SecondActivity時(shí),發(fā)現(xiàn)啟動(dòng)模式為singleTask您旁,那么設(shè)定他的啟動(dòng)標(biāo)志為FLAG_ACTIVITY_NEW_TASK
2. 然后獲得SecondActivity的taskAffinity烙常,即com.jg.zhang.androidtasktest.second
3. 檢查是否已經(jīng)存在一個(gè)affinity為com.jg.zhang.androidtasktest.second的任務(wù),這個(gè)任務(wù)是不存在的
4. 創(chuàng)建一個(gè)新的affinity為com.jg.zhang.androidtasktest.second的任務(wù)鹤盒,并且將SecondActivity啟動(dòng)到這個(gè)新的任務(wù)中
兩個(gè)不同app中的不同的singleTask模式的Activity的taskAffinity設(shè)成相同驗(yàn)證:**任務(wù)(Task)不僅可以跨應(yīng)用(Application)蚕脏,還可以跨進(jìn)程(Process)**
4. singleInstance
singleInstance的特點(diǎn)可以歸結(jié)為以下三條:
- 以singleInstance模式啟動(dòng)的Activity具有全局唯一性侦副,即整個(gè)系統(tǒng)中只會(huì)存在一個(gè)這樣的實(shí)例
- 以singleInstance模式啟動(dòng)的Activity具有獨(dú)占性,即它會(huì)獨(dú)自占用一個(gè)任務(wù)驼鞭,被他開(kāi)啟的任何activity都會(huì)運(yùn)行在其他任務(wù)中(官方文檔上的描述為秦驯,singleInstance模式的Activity不允許其他Activity和它共存在一個(gè)任務(wù)中)
- 被singleInstance模式的Activity開(kāi)啟的其他activity,能夠開(kāi)啟一個(gè)新任務(wù)挣棕,但不一定開(kāi)啟新的任務(wù)译隘,也可能在已有的一個(gè)任務(wù)中開(kāi)啟
使用場(chǎng)景
- singleTop
解決問(wèn)題:由于棧頂都是相同Activity而導(dǎo)致用戶(hù)出現(xiàn)BACK鍵失靈的錯(cuò)覺(jué)
a. APP的多個(gè)推送消息顯示在通知欄,你想把他們都給點(diǎn)了穴张,每次點(diǎn)擊實(shí)際就是啟動(dòng)某個(gè)Activity细燎,這時(shí)候如果使用的是singleTop模式,就可以有效避免重復(fù)創(chuàng)建同一Activity實(shí)例的工作皂甘。
b. 登錄成功跳轉(zhuǎn)到主頁(yè)玻驻,按下兩次登錄按鈕,生成了兩個(gè)主頁(yè)偿枕。一些有啟動(dòng)延遲的頁(yè)面(往往是動(dòng)畫(huà)璧瞬,網(wǎng)絡(luò)造成)也會(huì)有這樣的情況。 - singleTask
在創(chuàng)建開(kāi)銷(xiāo)較大且經(jīng)常被其他APP調(diào)用的Activity中使用渐夸,這種Activity一般作為程序的入口嗤锉。例如瀏覽器的主界面。不管從多少個(gè)應(yīng)用啟動(dòng)瀏覽器墓塌,只會(huì)啟動(dòng)主界面一次瘟忱,其余情況都會(huì)走onNewIntent,并且會(huì)清空主界面上面的其他頁(yè)面苫幢。 - singleInstance
單一實(shí)例模式访诱,整個(gè)手機(jī)操作系統(tǒng)里面只有一個(gè)實(shí)例存在。不同的應(yīng)用去打開(kāi)這個(gè)activity共享公用的同一個(gè)activity韩肝。這樣的Activity封閉性極強(qiáng)触菜,能夠很好地保持唯一性,也能大大減少不必要的開(kāi)銷(xiāo)哀峻。
某個(gè)應(yīng)用中用到了google地圖 當(dāng)退出該應(yīng)用的時(shí)候涡相,進(jìn)入google地圖,還是剛才的界面.
鬧鈴的響鈴界面 你以前設(shè)置了一個(gè)鬧鈴:上午6點(diǎn)剩蟀。在上午5點(diǎn)58分催蝗,你啟動(dòng)了鬧鈴設(shè)置界面,并按 Home 鍵回桌面育特;在上午5點(diǎn)59分時(shí)生逸,你在微信和朋友聊天;在6點(diǎn)時(shí),鬧鈴響了槽袄,并且彈出了一個(gè)對(duì)話(huà)框形式的 Activity(名為 AlarmAlertActivity) 提示你到6點(diǎn)了(這個(gè) Activity 就是以 SingleInstance 加載模式打開(kāi)的)烙无,你按返回鍵,回到的是微信的聊天界面遍尺,這是因?yàn)?AlarmAlertActivity 所在的 Task 的棧只有他一個(gè)元素截酷, 因此退出之后這個(gè) Task 的棧空了乾戏。如果是以 SingleTask 打開(kāi) AlarmAlertActivity迂苛,那么當(dāng)鬧鈴響了的時(shí)候,按返回鍵應(yīng)該進(jìn)入鬧鈴設(shè)置界面鼓择。