導(dǎo)語
我們陳述一下Activity,Activity是整個應(yīng)用用戶交互的核心組件,了解Activity的工作模式,生命周期和管理方式,是了解Android的基礎(chǔ)。
主要內(nèi)容
- Activity簡介
- Android任務(wù)棧簡介
- AndroidMainifest啟動模式
- Intent Flag啟動模式
- 清空任務(wù)棧
- Activity任務(wù)棧使用
具體內(nèi)容
Activity簡介
Activity作為四大組建出現(xiàn)平率最高的組件,我們在哪里都能看到他,就讓我們一起先來了解一下他的生命周期。
起源
Activity是用戶交互的第一接口,他提供了一個用戶完成指令的窗口,當(dāng)開發(fā)者創(chuàng)建Activity之后,通過調(diào)用setContentView來指定一個窗口界面,并以此為基礎(chǔ),提供給用戶交互的接口,系統(tǒng)采用Activity棧的方式來管理Activity。
Activity形態(tài)
Activity一個最大的特點就是擁有多種形態(tài),他可以在多種形態(tài)中自由切換,以此來控制自己的生命周期。
- Activity/Running:這個時候,Activity處于Activity棧的最頂層,可見,并與用戶進(jìn)行交互。
- Paused:Activity失去焦點,被一個新的非全屏的Activity或者一個透明的Activity放置在棧頂時,Activity就轉(zhuǎn)換成了qaused形態(tài),他是去了與用戶交互的能力,所有狀態(tài)信息,成員變量都還保留著,只有在系統(tǒng)內(nèi)存極地的情況下,才會被系統(tǒng)回收。
- Stopped:如果一個Activity被另一個Activity完全覆蓋,那么Activity就會進(jìn)入stop形態(tài),此時他不在可見,但依然保留著所有的狀態(tài)和成員變量。
- Killed:當(dāng)Activity被系統(tǒng)回收或者Activity從來沒有創(chuàng)建過,Activity就處于killed狀態(tài)。
由此可見,用戶的不同操作,會讓Activity進(jìn)入四種不同的狀態(tài),而開發(fā)者,只能控制其生,卻不能控制其死。
生命周期
Google給了我們一張圖來表示Activity的生命周期,他希望Activity能被開發(fā)者所控制,而不是一匹脫韁的野馬。

開發(fā)者必然不必實現(xiàn)所有的生命周期方法,但是必須知道每一個生命周期的含義,可以讓我們更好的掌控Activity,讓他能完成你所期望的效果。
Activity啟動和銷毀過程
在系統(tǒng)調(diào)用onCreate方法之后,就會馬上調(diào)用onStart,然后繼續(xù)調(diào)用onResume來進(jìn)圖運行狀態(tài),最后都會停在onResume狀態(tài),完成啟動,系統(tǒng)會調(diào)用onDestroy來結(jié)束一個Activity的生命周期讓他毀掉kill狀態(tài)。
以上就是一個Activity的啟動和銷毀的過程。
- onCreate中創(chuàng)建基本的UI元素。
- onPause和onStop:清除Acvtivity的資源,避免浪費。
- onDestroy:因為引用會在Activity銷毀的時候銷毀,而線程不會,所以清除開啟的線程。
Activity的暫停和恢復(fù)過程
當(dāng)棧頂?shù)腁ctivity部分不可見的時候,就會倒置Activity進(jìn)入onPause。
- onPause:釋放系統(tǒng)資源。
- onResume:需要重新初始化onPause釋放的資源。
Activity的停止過程
棧頂?shù)腁ctivity部分不可見的時候,實際上后續(xù)會有兩種可能,從部分不可見到可見,也就是恢復(fù)過程,從部分不可見到完全不可見,也就是停止過程,系統(tǒng)在當(dāng)前Activity不可見的時候調(diào)用onPause。
Activity的重新創(chuàng)建過程
最后我們來看看Activity是如何重新創(chuàng)建的,如果你的系統(tǒng)長時間處于stop的狀態(tài),而此時系統(tǒng)需要更多的內(nèi)存或者系統(tǒng)內(nèi)存比較緊張的時候,系統(tǒng)就會回收你的Activity,而系統(tǒng)為了補(bǔ)償你,會將你的Activity狀態(tài)通過onRestoreInstanceState()方法保存到Bundle中去,當(dāng)然你也可以額外增加鍵值對去保存這些狀態(tài),當(dāng)你重新需要創(chuàng)建這個Activity的時候,保存的Bundle對象就會傳遞到Activity的onRestoreInstanceState()方法中去與onCreate方法中去,這也是onCreate的重要參數(shù)——saveInstanceState的來源。
不過這里要注意的一點就是savedInstanceState方法并不是每次當(dāng)Activity離開前臺就會調(diào)用,如果用戶使用finish方法結(jié)束,則不會調(diào)用,而且Android系統(tǒng)已經(jīng)默認(rèn)實現(xiàn)了控件的緩存狀態(tài),一次來減少開發(fā)者需要實現(xiàn)的緩存邏輯。
Android任務(wù)棧簡介
- 當(dāng)一個App啟動時,如果當(dāng)前環(huán)境下不存在該App的任務(wù)棧,那么系統(tǒng)就會創(chuàng)建一個任務(wù)棧,此后,這個App所啟動的Activity都將在這個任務(wù)棧中被管理,這個棧也被稱為一個Task,即表示若干個Activity的集合,他們組成在一起形成一個Task,特別要注意的是,一個Task中的Activity可以來自不同的App,同一個App的Activity也可能不在一個Task中。
- 棧的結(jié)構(gòu)是后進(jìn)先出的線性表,通過在AndroidManifest文件中的屬性android:launchMode來設(shè)置或者是通過Intent的flag來設(shè)置的。
AndroidMainifest啟動模式
Android開發(fā)者可以在AndroidManifest文件中一共設(shè)計了四種啟動模式:
- standard
- singleTop
- singleTask
- singleInstance
standard
默認(rèn)的啟動模式,如果不指定Activity的啟動模式,則使用這種模式來啟動Activity,每次點擊standard模式創(chuàng)建Activity之后,都會創(chuàng)建新的MainActivity覆蓋在原有的Activity上,如下圖。

singleTop
如果指定Activity的啟動方式為singletop,那么在啟動的時候,系統(tǒng)會判斷當(dāng)前棧頂Activity是不是要啟動的那個,如果是則不創(chuàng)建新的Activity,如果不是則創(chuàng)建新的Activity,這種模式通常適用于接收到消息后顯示的界面,列入QQ接收到消息后彈出Activity,如果一次來10條,總不能彈10次吧,這種啟動模式的如下圖。

這種啟動模式雖然不能創(chuàng)建新的實例,但是系統(tǒng)任然會在Activity啟動的時候調(diào)用onNewIntent()方法,舉例子,如果當(dāng)前任務(wù)棧中有ABC三個Activity,而C的啟動模式是singleTop,那么這個時候再啟動C,那么系統(tǒng)就不會去創(chuàng)建C的實例了,而是會調(diào)用C的onNewIntent方法,當(dāng)前任務(wù)棧依然是ABC三個Activity。
singleTask
singleTask模式和singleTop模式有點類似,只不過singleTop是檢測棧頂元素是否需要啟動的Activity,而singleTask是檢測整個Activity棧中是否存在當(dāng)前啟動的Activity,如果存在,就將他置于棧頂,并且將以上的activity全部銷毀,不過這里也是指在同一個APP中啟動整個singleTask的Activity,如果是其他的程序以singleTask模式來啟動整個Activity,那么他將創(chuàng)建一個新的任務(wù)棧,不過這里有一點需要注意的是,如果啟動的模式為singleTask的activity已經(jīng)在后臺的一個棧中,那么啟動后,后臺的一個任務(wù)棧將一起被切換到前臺,借助官網(wǎng)的一張圖我們可能更好的理解。

當(dāng)Activity2啟動ActivityY的時候(啟動模式為singleTask),他所在的task被切換到前臺,且按返回鍵返回的時候,也會先返回ActivityY所在Task的Activity,這一點比較難理解,大家根據(jù)圖去研究一下。
可以發(fā)現(xiàn),使用這個模式創(chuàng)建的Activity不是在新的任務(wù)棧中被打開,就是將已打開的Activity換到前臺,所以這種啟動模式通??梢杂脕硗顺稣麄€應(yīng)用,將主Activity設(shè)為singleTask模式,然后在要退出的Activity中轉(zhuǎn)到主Activity,從而將主Activity之上的Activity全部銷毀,然后重寫主Activity的onNewIntent()方法 在方法中加上一句finish(),將最后一個Activity結(jié)束掉。
singleInstance
singieInstance這種啟動模式和使用的瀏覽器工作原理類似。在多個程序中訪問瀏覽器時,如果當(dāng)前瀏覽器沒有打開則打開瀏覽器,否則會在當(dāng)前打開的瀏覽器中訪問。申明為singleInstance的Activity會出現(xiàn)在一個新的任務(wù)棧中而且該任務(wù)棧中只存在這一個Activity,舉個例子來說,如果應(yīng)用A的任務(wù)棧中創(chuàng)建了MainActivity實例,且啟動模式為singleInstance,如果應(yīng)用B也要激活MainActivity則不需要創(chuàng)建,兩個應(yīng)用共享該Activity實例,這種啟動模式常用于需要與程序分離的界面:如在SetupWizard中調(diào)用緊急呼叫,就是使用這種啟動模式。
關(guān)于singleTop和singleInstance這兩種啟動模式還有一點需要特殊說明:如果在一個singleTop或者singleInstance的Activity中通過startActivityForResult()方法來啟動另一個ActivityB, 那么系統(tǒng)將直接返回Activity_RESULT_CANCELED而不會再去等待返回。這是由于系統(tǒng)在framework層做了對這兩種啟動模式的限制,因為Android開發(fā)者認(rèn)為,不同的Task中,默認(rèn)是不能傳遞數(shù)據(jù)的。如果一定要傳遞數(shù)據(jù)的話,那么只能通過Intent去綁定數(shù)據(jù)。
Intent Flag啟動模式
前面就已經(jīng)說了,系統(tǒng)提供了兩種方式來設(shè)置一個Activity的啟動模式,下面要講的是通過Intent設(shè)置Flag來設(shè)置一個Activity的啟動模式。
常用的Flag:
- Intent.FLAG_ACTIVITY_NEW_TASK:使用一個新的Task來啟動一個Activity,但啟動的每個Activity都將在一個新的Task中,該Flag通常使用在從service中啟動的activity場景,由于在Service中并不存在Activity棧,所以使用該Flag來創(chuàng)建一個新的Activity棧,并創(chuàng)建新的Activity實例。
- FLAG_ACTIVITY_SINGLE_TOP:使用singleTop模式來啟動一個Activity,與指定android:launchMode=”singleTop”效果相同。
- FLAG_ACTIVITY_CLEAR_TOP:使用SingleTask模式來啟動一個Activity,與指定android:launchMode=”singleTask”效果相同。
- FLAG_ACTIVITY_NO_HISTORY:使用這種模式啟動Activity,當(dāng)該Activity啟動其他Activity后,該Activity就消失了,不會保留在Activity棧中,例如A-B,B中以這種模式啟動C,C再啟動D,則當(dāng)前Activity棧為ABD。
清空任務(wù)棧
系統(tǒng)同樣提供了清空任務(wù)棧的方法來讓我們講一個Task清空,通常情況下,我們可以在activity的標(biāo)簽上使用以下幾種屬性來清空任務(wù)棧。
清空任務(wù)棧:
- clearTaskOnLaunch:每次返回Activity的時候,都將該Activity上的所有Activity都清除,通過這個屬性,可以讓這個Task每次初始化的時候,都只有一個Activity。
- finishTaskOnLaunch:這個屬性和clearTaskOnLaunch有點類似,只不過clearTaskOnLaunch作用在別人身上,而finishTaskOnLaunch作用在自己身上,通過這個屬性,當(dāng)離開這個Activity所處的Task,那么用戶再返回的時候,該Activity會被finish掉。
- alwaysRetainTaskState:Task的一道免死金牌,如果將Activity這個屬性設(shè)置為true,那么該Activity所在的Task將不接受任何清除命令,一直保持當(dāng)前Task的狀態(tài)。
Activity任務(wù)棧使用
我們使用Activity任務(wù)棧的各種啟動模式和清理方法,是為了更好地使用App中Activity,合理地設(shè)置Activity的啟動模式會讓程序運行更有效率,用戶體驗更好。但任務(wù)棧雖好,卻也不能濫用,如果過度地使用Activity任務(wù)棧,則會導(dǎo)致整個App的棧管理混亂,不利于以后程序的拓展,而且在容易出現(xiàn)由于任務(wù)棧導(dǎo)致的顯示異常,這樣的bug是很難調(diào)的。所以,在App中使用Activity任務(wù)棧一定要根據(jù)實際項目的需要,而不是為了使用任務(wù)棧而使用任務(wù)棧。