關(guān)于四種啟動(dòng)模式的分析可以參考下我上一篇文章 “Android Activity4種啟動(dòng)模式的詳解”。
singleInstance(全局單例模式)該模式具備singleTask模式的所有特性外,與它的區(qū)別就是,這種模式下的Activity會(huì)單獨(dú)占用一個(gè)Task棧,具有全局唯一性,即整個(gè)系統(tǒng)中就這么一個(gè)實(shí)例,由于棧內(nèi)復(fù)用的特性,后續(xù)的請(qǐng)求均不會(huì)創(chuàng)建新的Activity實(shí)例,除非這個(gè)特殊的任務(wù)棧被銷毀了。以singleInstance模式啟動(dòng)的Activity在整個(gè)系統(tǒng)中是單例的,如果在啟動(dòng)這樣的Activiyt時(shí),已經(jīng)存在了一個(gè)實(shí)例,那么會(huì)把它
所在的任務(wù)調(diào)度到前臺(tái),重用這個(gè)實(shí)例。
簡(jiǎn)而言之,采用這種啟動(dòng)模式啟動(dòng)一個(gè)Activity,會(huì)創(chuàng)建一個(gè)新的棧存放該Activity的實(shí)例,并且這個(gè)棧中有且僅有這一個(gè)實(shí)例。
最近在項(xiàng)目中遇見了一個(gè)bug,雖然后面解決了,這里記錄下也是給其他人的一個(gè)參考。
大致情況是這樣:
從主頁(yè)面


錯(cuò)誤排查:首先想到的是back鍵的事件方法,
@Overridepublic voidonBackPressed() {? ? finish();overridePendingTransition(R.anim.in_from_left,R.anim.out_from_right);}
新聞Activity的返回事件處理方法就是直接結(jié)束這個(gè)頁(yè)面,沒有錯(cuò)啊,難道要我使用暴力解決法,
@Overridepublic voidonBackPressed() {? ? finish();startActivity(newIntent(this,MainActivity.class));overridePendingTransition(R.anim.in_from_left,R.anim.out_from_right);}
直接在返回事件強(qiáng)制切換到主頁(yè)面,這個(gè)方法果然行得通。但是仔細(xì)思考了下,之所以會(huì)出現(xiàn)前面的錯(cuò)誤,是不是在切換到后臺(tái)后activity的生命周期方法的處理存在邏輯問題,排查后也沒有發(fā)現(xiàn)錯(cuò)誤。
這時(shí)候無(wú)意發(fā)現(xiàn)是MainActivity的啟動(dòng)模式是singleInstance,參考網(wǎng)上意見改成standard的默認(rèn)模式后果然Bug解決了??墒菫槭裁磗ingleInstance會(huì)出現(xiàn)這種問題呢?
由MainActivity切換到ActivityA,用戶按home鍵返回桌面,系統(tǒng)會(huì)將此時(shí)的task打包進(jìn)行狀態(tài)保存,也就是說(shuō)位于棧內(nèi)的每個(gè)Activity狀態(tài)都被保存下來(lái)了。用戶重新啟動(dòng)激活該task,位于棧頂?shù)腁ctivity 可見并走onResume方法。由于MainActivity的加載模式是singleInstance而ActivityA則是默認(rèn)方式,這導(dǎo)致了兩個(gè)Activity位于不同的任務(wù)棧task中,當(dāng)我返回桌面后重新切回應(yīng)用,這時(shí)按下返回鍵會(huì)將A的task中唯一的一個(gè)實(shí)例A出棧,導(dǎo)致taskA為空,應(yīng)用直接結(jié)束。
而將MainActivity的啟動(dòng)模式改為默認(rèn)模式后,MainActivity和A的實(shí)例位于同一個(gè)任務(wù)棧task中,執(zhí)行前面的操作,按下返回鍵后A出棧,此時(shí)task中剩下MainActivity位于棧頂來(lái)到前臺(tái),Bug解決。
這里補(bǔ)充下task的概念:Android系統(tǒng)下,當(dāng)用戶為了完成某一個(gè)功能可能需要進(jìn)行多個(gè)Actvitiy間的跳轉(zhuǎn)才能達(dá)到目的,這些Activity的跳轉(zhuǎn)序列就被Android抽象成了一個(gè)Task。而這一組Actvitiy實(shí)例都被放到了同一個(gè)棧中,先啟動(dòng)的Activity位于棧底,最后到達(dá)的Activity位于棧頂。一般而言Task的啟動(dòng)點(diǎn)都是從home 界面算起,點(diǎn)擊Launcher界面的應(yīng)用icon,如果之前沒有啟動(dòng)過(guò),則系統(tǒng)新建一個(gè)Task,剛啟動(dòng)應(yīng)用的主Activiy被壓入棧底,棧內(nèi)的Activity是不會(huì)在內(nèi)部重新排列的,只能按先入后出的順序呈現(xiàn),當(dāng)用戶連續(xù)按back鍵,使得棧底的Activity也pop出棧,棧為空了,這時(shí)該Task結(jié)束。
覺得有用的朋友麻煩點(diǎn)個(gè)贊,畢竟更文不易,你的一點(diǎn)支持可能是我莫大的動(dòng)力!