Activity小結(jié)

Activity是一個(gè)應(yīng)用組件, 單個(gè)的Activity代表一個(gè)單獨(dú)的屏幕界面,用戶可與其提供的屏幕進(jìn)行交互。

一、任務(wù)和返回棧

一個(gè)應(yīng)用通常包含多個(gè)Activity,Android系統(tǒng)使用任務(wù)(Task)來(lái)管理這些Activity,一個(gè)任務(wù)就是一組存放在棧里的Activity的集合,這個(gè)棧也叫做返回棧,Activity 按照各自的打開(kāi)順序排列在棧(即返回棧)中。
  任務(wù)(Task)是可以跨應(yīng)用的,這正是任務(wù)存在的一個(gè)重要原因。有的Activity,雖然不在同一個(gè)應(yīng)用中,但為了保持用戶操作的連貫性,把他們放在同一個(gè)任務(wù)中。例如,在我們的應(yīng)用中的一個(gè)Activity A中點(diǎn)擊發(fā)送郵件,會(huì)啟動(dòng)郵件程序的一個(gè)Activity B來(lái)發(fā)送郵件,這兩個(gè)activity是存在于不同應(yīng)用中的,但是被系統(tǒng)放在一個(gè)任務(wù)中,這樣當(dāng)發(fā)送完郵件后,用戶按back鍵返回,可以返回到原來(lái)的Activity A中,這樣就確保了用戶體驗(yàn)。


返回棧

  我們知道,棧是一種“后進(jìn)先出”的數(shù)據(jù)結(jié)構(gòu),默認(rèn)情況下,每創(chuàng)建一個(gè)新的Activity,它會(huì)在返回棧中入棧,并處于棧頂位置。當(dāng)我們按下返回按鈕或者調(diào)用finish()銷毀棧頂活動(dòng)時(shí),位于棧頂?shù)幕顒?dòng)出棧,前一個(gè)棧即成為新的棧頂。系統(tǒng)總是會(huì)顯示處于棧頂?shù)腁ctivity給用戶。

二、Activity 生命周期

(1)Activity的四種狀態(tài)

Activity在其生命周期中最多有四種狀態(tài):

  • 運(yùn)行狀態(tài)
    當(dāng)一個(gè)Activity位于返回棧的棧頂時(shí),該Activity就處于運(yùn)行狀態(tài)。
  • 暫停狀態(tài)
    當(dāng)一個(gè)Activity不處于棧頂位置但仍可見(jiàn)時(shí),該Activity就處于暫停狀態(tài)。例如,若一個(gè)Activity被一個(gè)彈出的未占滿屏幕的對(duì)話框Activity遮住了,但是未完全遮住,則此時(shí)該Activity就處于暫停狀態(tài)
  • 停止?fàn)顟B(tài)
    當(dāng)一個(gè)Activity不再處于棧頂位置且完全不可見(jiàn)時(shí),該Activity就處于停止?fàn)顟B(tài)
  • 銷毀狀態(tài)
    當(dāng)一個(gè)Activity從返回棧中移除后就進(jìn)入了銷毀狀態(tài)。
      以上四種狀態(tài)的Activity,為了保證手機(jī)內(nèi)存充足,系統(tǒng)最傾向于回收銷毀狀態(tài)的Activity,其次是處于停止?fàn)顟B(tài)的Activity,對(duì)于可見(jiàn)狀態(tài)(暫停狀態(tài)和運(yùn)行狀態(tài))的Activity,只有在內(nèi)存極低的情況下系統(tǒng)才會(huì)考慮回收,且系統(tǒng)最不愿意回收處于運(yùn)行狀態(tài)的Activity,因?yàn)榇藭r(shí)的Activity正與用戶直接交互,若強(qiáng)行回收會(huì)帶來(lái)極差的用戶體驗(yàn)。

(2)Activity的七種回調(diào)方法

Activity的生命周期

如上圖所示,Activity類定義了七個(gè)回調(diào)方法來(lái)表示Activity生命周期的不同環(huán)節(jié):

  • onCreate()
    在Activity第一次被創(chuàng)建的時(shí)候調(diào)用。
  • onStart()
    當(dāng)Activity由不可見(jiàn)變?yōu)榭梢?jiàn)狀態(tài)時(shí)調(diào)用。
  • onResume()
    當(dāng)Activity準(zhǔn)備好與用戶進(jìn)行交互時(shí)調(diào)用。此時(shí)活動(dòng)一定處于運(yùn)行狀態(tài),且位于返回棧棧頂。
  • onPause()
    在系統(tǒng)準(zhǔn)備去啟動(dòng)或者恢復(fù)另一個(gè)Activity時(shí)調(diào)用。該方法一般用于保存一些關(guān)鍵數(shù)據(jù)以及釋放掉一些消耗CPU的資源。
  • onStop()
    在Activity完全不可見(jiàn)時(shí)調(diào)用。
  • onDestory()
    在Activity被銷毀之前調(diào)用。之后Activity即變?yōu)殇N毀狀態(tài)。
  • onRestart()
    在Activity由停止?fàn)顟B(tài)變?yōu)檫\(yùn)行狀態(tài)之前調(diào)用,也即Activity被重新啟動(dòng)了

(3)Activity的三種生存期

以上七個(gè)方法中,出了onRestart()方法,其他方法都是兩兩對(duì)應(yīng)的,我們可以將Activity分為三種生存期:
(1)完整生存期:onCreate()<-->onDestory()
(2)可見(jiàn)生存期:onStart()<-->onStop()
(3)前臺(tái)生存期:onResume()<-->onPause()

(4)Activity的幾種典型生命周期變化

我總結(jié)了幾種典型情況下Activity的生命周期的變化:

  • Activity第一次被創(chuàng)建時(shí)依次執(zhí)行:
    onCreate()-->onStart()-->onResume()
  • Activity被另一個(gè)Activity遮擋時(shí)(完全遮擋)依次執(zhí)行:
    onPause()-->onStop()
  • 然后按下back鍵返回上一個(gè)Activity:
    onRestart()-->onStart()-->onResume()
  • 打開(kāi)另一個(gè)對(duì)話框形式的Activity(部分遮擋):
    onPause()-->按下back鍵返回-->onResume()
  • 按下back鍵退出程序:
    onPause()-->onStop()-->onDestroy()

(5)Activity被回收的處理
  在 Activity 生命周期中,Android 會(huì)在銷毀 Activity 之前調(diào)用onSaveInstanceState(),以便保存有關(guān)應(yīng)用狀態(tài)的數(shù)據(jù)。

@Override
    public void onSaveInstanceState(Bundle savedInstanceState)
    {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putString("message", text.getText().toString());
    }

我們可以在onCreate()中取出Activity銷毀之前保存的數(shù)據(jù)來(lái)恢復(fù) Activity 狀態(tài)。

@Override
protected void onCreate(Bundle savedInstanceState)
 {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if(savedInstanceState != null)
      {
         String message = savedInstanceState.getString("message");
      }
 }

除了在onCreate()中恢復(fù)外,我們還可以使用onRestoreInstanceState()函數(shù)來(lái)恢復(fù)數(shù)據(jù),如下所示:

@Override
public void onRestoreInstanceState(Bundle savedInstanceState)
{
    super.onRestoreInstanceState(savedInstanceState);
    String message = savedInstanceState.getString("message");
}

需要注意的是,onSaveInstanceState()和onRestoreInstanceState()并不同于Activity的生命周期方法,它們并不一定會(huì)被觸發(fā)。
  例如,當(dāng)應(yīng)用遇到意外情況(如:內(nèi)存不足、用戶直接按Home鍵)由系統(tǒng)銷毀一個(gè)Activity時(shí),onSaveInstanceState() 會(huì)被調(diào)用。但是當(dāng)用戶主動(dòng)去銷毀一個(gè)Activity時(shí),例如在應(yīng)用中按返回鍵,onSaveInstanceState()就不會(huì)被調(diào)用。因?yàn)樵谶@種情況下,用戶的行為決定了不需要保存Activity的狀態(tài)。
  而onRestoreInstanceState()被調(diào)用的前提是,Activity確實(shí)被系統(tǒng)銷毀了,而不是有可能被銷毀。例如,當(dāng)正在顯示activity A的時(shí)候,用戶按下HOME鍵回到主界面,然后用戶緊接著又返回到Activity A,這種情況下Activity A一般不會(huì)因?yàn)閮?nèi)存的原因被系統(tǒng)銷毀,故Activity A的onRestoreInstanceState()方法不會(huì)被執(zhí)行。
  通常onSaveInstanceState()只適合用于保存一些臨時(shí)性的狀態(tài),而onPause()適合用于數(shù)據(jù)的持久化保存。

三、Activity的啟動(dòng)模式

Activity有四種啟動(dòng)模式,分別為standard,singleTop,singleTask,singleInstance。如果要使用這四種啟動(dòng)模式,必須在manifest文件中<activity>標(biāo)簽中的launchMode屬性中配置,如下所示,若不配置的話,默認(rèn)為standard模式:

<activity android:name=".MainActivity"  
          android:label="@string/title_name"  
          android:theme="@android:style/Theme.Holo.Light"  
          android:launchMode="singleTask"  
</activity> 
  • standard 標(biāo)準(zhǔn)模式,每次都新建一個(gè)實(shí)例對(duì)象
  • singleTop 如果在任務(wù)棧頂發(fā)現(xiàn)了相同的實(shí)例(注意是棧頂),則調(diào)用原來(lái)?xiàng)m攲?shí)例的onNewIntent()方法來(lái)重用該實(shí)例,而不是新建一個(gè)實(shí)例。否則新建并壓入棧頂
  • singleTask 如果在任務(wù)棧中發(fā)現(xiàn)了相同的實(shí)例,將其上面的任務(wù)終止并移除,重用該實(shí)例。否則新建實(shí)例并入棧
  • singleInstance 允許不同應(yīng)用,進(jìn)程線程等共用一個(gè)實(shí)例,無(wú)論從何應(yīng)用調(diào)用該實(shí)例都重用

為了便于理解,特意畫了幾張示意圖說(shuō)明:
(1)standard:每次激活A(yù)ctivity時(shí)(startActivity),都創(chuàng)建Activity實(shí)例,并放入任務(wù)棧。

standard模式

從圖中可以看出,雖然當(dāng)前棧頂為Activty2,但若再開(kāi)啟一個(gè)Activity2仍然會(huì)新建一個(gè)實(shí)例壓入棧中成為新的棧頂。這種模式其實(shí)并不合理,每次都新建一個(gè)實(shí)例實(shí)在是浪費(fèi)。事實(shí)上,我們可以根據(jù)實(shí)際情況采用下面的三種方式來(lái)進(jìn)行優(yōu)化。

(2)singleTop:如果某個(gè)Activity自己激活自己,即任務(wù)棧棧頂就是該Activity,則不需要?jiǎng)?chuàng)建,其余情況都要?jiǎng)?chuàng)建Activity實(shí)例。

singleTop模式

采用這種模式可以很好地解決重復(fù)棧頂?shù)膯?wèn)題,但是若活動(dòng)并不處于棧頂,還是會(huì)重復(fù)創(chuàng)建多個(gè)實(shí)例。有沒(méi)有辦法可以讓整個(gè)應(yīng)用程序的上下文只存在某個(gè)Activity的一個(gè)實(shí)例呢?這就要用到singleTask模式了。

(3)singleTask:如果要激活的那個(gè)Activity在任務(wù)棧中存在該實(shí)例,則不需要?jiǎng)?chuàng)建,只需要把此Activity放入棧頂,并把該Activity以上的Activity實(shí)例都從棧中移除。

singleTask模式

從上圖中可以看到,當(dāng)前棧頂為Activity3,開(kāi)啟Activity1,此時(shí)棧中存在Activity1,則將Activity1上面的Activity3、Activity2移除,使Activity1成為新的棧頂。
  singleTop和singleTask看起來(lái)已經(jīng)可以解決大部分重復(fù)創(chuàng)建實(shí)例的問(wèn)題了。但是,若某個(gè)應(yīng)用的某個(gè)Activity頻繁被其他應(yīng)用調(diào)用,那么情況又會(huì)怎樣呢?我們知道,每個(gè)應(yīng)用都會(huì)有自己的返回棧,同一個(gè)Activity被不同應(yīng)用調(diào)用,必然會(huì)在不同應(yīng)用的返回棧中都創(chuàng)建新的實(shí)例,而使用singleInstance就可以解決這個(gè)問(wèn)題了。

(4)singleInstance:如果應(yīng)用1的任務(wù)棧中創(chuàng)建了MainActivity實(shí)例,如果應(yīng)用2也要激活MainActivity,則不需要?jiǎng)?chuàng)建,兩應(yīng)用共享該Activity實(shí)例;


singleInstance模式

從上圖中可以看到,Activity3存放在一個(gè)單獨(dú)的返回棧里,在singleInstance中,會(huì)有一個(gè)單獨(dú)的返回棧來(lái)管理某個(gè)被其他應(yīng)用頻繁調(diào)用的Activity,不管哪個(gè)應(yīng)用來(lái)訪問(wèn)這個(gè)Activity,都共用同一個(gè)返回棧,這也就解決了應(yīng)用間共享Activity實(shí)例的問(wèn)題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容