了解 Activity 生命周期

當(dāng)用戶瀏覽、退出和返回到您的應(yīng)用時(shí)筐钟,您應(yīng)用中的 [Activity](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn) 實(shí)例會(huì)在其生命周期的不同狀態(tài)間轉(zhuǎn)換揩瞪。[Activity](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn) 類會(huì)提供許多回調(diào),這些回調(diào)會(huì)讓 Activity 知曉某個(gè)狀態(tài)已經(jīng)更改:系統(tǒng)正在創(chuàng)建篓冲、停止或恢復(fù)某個(gè) Activity李破,或者正在銷毀該 Activity 所在的進(jìn)程。

在生命周期回調(diào)方法中壹将,您可以聲明用戶離開和再次進(jìn)入 Activity 時(shí) Activity 的行為方式嗤攻。例如,如果您正構(gòu)建流媒體視頻播放器诽俯,當(dāng)用戶切換至另一應(yīng)用時(shí)妇菱,您可能要暫停視頻或終止網(wǎng)絡(luò)連接。當(dāng)用戶返回時(shí)暴区,您可以重新連接網(wǎng)絡(luò)并允許用戶從同一位置繼續(xù)播放視頻闯团。換言之,每個(gè)回調(diào)都支持您執(zhí)行適合給定狀態(tài)變更的特定作業(yè)仙粱。在合適的時(shí)間執(zhí)行正確的作業(yè)房交,并妥善處理轉(zhuǎn)換,這將提升應(yīng)用的穩(wěn)健性和性能伐割。例如候味,良好的生命周期回調(diào)實(shí)現(xiàn)有助于防止應(yīng)用出現(xiàn)以下問(wèn)題:

? 當(dāng)用戶在使用應(yīng)用時(shí)接聽來(lái)電,或切換至另一應(yīng)用時(shí)崩潰隔心。
? 當(dāng)用戶未主動(dòng)使用它時(shí)负溪,消耗寶貴的系統(tǒng)資源。
? 當(dāng)用戶離開應(yīng)用并在稍后返回時(shí)济炎,丟失用戶的進(jìn)度川抡。
? 當(dāng)屏幕在橫向和縱向之間旋轉(zhuǎn)時(shí),崩潰或丟失用戶的進(jìn)度须尚。

本文檔將詳細(xì)介紹 Activity 生命周期崖堤。首先介紹生命周期范例。接著介紹每個(gè)回調(diào):它們執(zhí)行時(shí)內(nèi)部發(fā)生了什么耐床,以及您應(yīng)該在執(zhí)行期間實(shí)現(xiàn)什么密幔。然后,簡(jiǎn)要介紹 Activity 狀態(tài)與導(dǎo)致進(jìn)程被系統(tǒng)終止的漏洞之間的關(guān)系撩轰。最后胯甩,討論與在 Activity 狀態(tài)之間轉(zhuǎn)換相關(guān)的若干主題酸役。

如需了解有關(guān)處理生命周期的信息(包括最佳做法的相關(guān)指導(dǎo))击敌,請(qǐng)參閱使用生命周期感知型組件處理生命周期保存界面狀態(tài)。如需了解如何將 Activity 與架構(gòu)組件結(jié)合使用,以構(gòu)建生產(chǎn)質(zhì)量的穩(wěn)健應(yīng)用馁蒂,請(qǐng)參閱應(yīng)用架構(gòu)指南兴喂。

Activity 生命周期概念

為了在 Activity 生命周期的各個(gè)階段之間導(dǎo)航轉(zhuǎn)換印荔,Activity 類提供六個(gè)核心回調(diào):[onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle))械哟、[onStart()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStart())[onResume()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onResume())怜森、[onPause()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onPause())速挑、[onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop())[onDestroy()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onDestroy())。當(dāng) Activity 進(jìn)入新狀態(tài)時(shí)副硅,系統(tǒng)會(huì)調(diào)用其中每個(gè)回調(diào)姥宝。

圖 1 是對(duì)此范例的直觀展現(xiàn)。

image.png

圖 1. Activity 生命周期的簡(jiǎn)化圖示恐疲。

當(dāng)用戶開始離開 Activity 時(shí)伶授,系統(tǒng)會(huì)調(diào)用方法來(lái)銷毀該 Activity。在某些情況下流纹,此銷毀只是部分銷毀;Activity 仍然駐留在內(nèi)存中(例如當(dāng)用戶切換至另一應(yīng)用時(shí))违诗,并且仍然可以返回到前臺(tái)漱凝。如果用戶返回到該 Activity,Activity 會(huì)從用戶離開時(shí)的位置繼續(xù)運(yùn)行诸迟。除了少數(shù)例外茸炒,應(yīng)用在后臺(tái)運(yùn)行時(shí)會(huì)受到限制,無(wú)法啟動(dòng) Activity阵苇。

系統(tǒng)終止給定進(jìn)程及其中 Activity 的可能性取決于當(dāng)時(shí) Activity 的狀態(tài)壁公。Activity 狀態(tài)和從內(nèi)存中彈出 會(huì)更詳細(xì)地介紹狀態(tài)與彈出漏洞之間的關(guān)系。

根據(jù) Activity 的復(fù)雜程度绅项,您可能不需要實(shí)現(xiàn)所有生命周期方法紊册。但是,請(qǐng)務(wù)必了解每個(gè)方法快耿,并實(shí)現(xiàn)能夠確保應(yīng)用按用戶預(yù)期方式運(yùn)行的方法囊陡,這非常重要。

在下一部分中掀亥,本文檔將詳細(xì)介紹用于處理狀態(tài)間轉(zhuǎn)換的回調(diào)撞反。

生命周期回調(diào)

本部分介紹 Activity 生命周期中所用回調(diào)方法的相關(guān)概念及實(shí)現(xiàn)信息。

某些操作(例如調(diào)用 [setContentView()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#setContentView(int)))屬于 Activity 生命周期方法本身搪花。不過(guò)遏片,用于實(shí)現(xiàn)依賴組件操作的代碼應(yīng)放在組件本身內(nèi)嘹害。為此,您必須使依賴組件具有生命周期感知能力吮便。請(qǐng)參閱使用生命周期感知型組件處理生命周期笔呀,了解如何讓您的依賴組件獲得生命周期感知能力。

onCreate()

您必須實(shí)現(xiàn)此回調(diào)线衫,它會(huì)在系統(tǒng)首次創(chuàng)建 Activity 時(shí)觸發(fā)凿可。Activity 會(huì)在創(chuàng)建后進(jìn)入“已創(chuàng)建”狀態(tài)。*[onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle))* 方法中授账,您需執(zhí)行基本應(yīng)用啟動(dòng)邏輯枯跑,該邏輯在 Activity 的整個(gè)生命周期中只應(yīng)發(fā)生一次。例如白热,*[onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle))** 的實(shí)現(xiàn)可能會(huì)將數(shù)據(jù)綁定到列表敛助,將 Activity 與 *[ViewModel](https://developer.android.google.cn/reference/androidx/lifecycle/ViewModel?hl=zh-cn)* 相關(guān)聯(lián),并實(shí)例化某些類作用域變量屋确。此方法會(huì)接收 *savedInstanceState* 參數(shù)纳击,后者是包含 Activity 先前保存狀態(tài)的 *[Bundle](https://developer.android.google.cn/reference/android/os/Bundle?hl=zh-cn)* 對(duì)象。如果 Activity 此前未曾存在攻臀,*[Bundle](https://developer.android.google.cn/reference/android/os/Bundle?hl=zh-cn)* 對(duì)象的值為 null焕数。*

如果您有一個(gè)生命周期感知型組件與您的 Activity 生命周期相關(guān)聯(lián),該組件將收到 [ON_CREATE](https://developer.android.google.cn/reference/androidx/lifecycle/Lifecycle.Event?hl=zh-cn#ON_CREATE) 事件刨啸。系統(tǒng)將調(diào)用帶有 @OnLifecycleEvent 注釋的方法堡赔,以使您的生命周期感知型組件可以執(zhí)行已創(chuàng)建狀態(tài)所需的任何設(shè)置代碼。

[onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle)) 方法的以下示例顯示執(zhí)行 Activity 某些基本設(shè)置的一些代碼设联,例如聲明界面(在 XML 布局文件中定義)善已、定義成員變量,以及配置某些界面离例。在本示例中换团,系統(tǒng)通過(guò)將文件的資源 ID R.layout.main_activity 傳遞給 [setContentView()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#setContentView(android.view.View)) 來(lái)指定 XML 布局文件。

KotlinJava

<select><option value="">--</option><option value="javascript">javascript</option><option value="typescript">typescript</option><option value="bash">bash</option><option value="sql">sql</option><option value="json">json</option><option value="html">html</option><option value="css">css</option><option value="c">c</option><option value="cpp">cpp</option><option value="java">java</option><option value="ruby">ruby</option><option value="python">python</option><option value="go">go</option><option value="rust">rust</option><option value="markdown">markdown</option></select>

lateinit var textView: TextView

// some transient state for the activity instance
var gameState: String? = null

override fun onCreate(savedInstanceState: Bundle?) {
    // call the super class onCreate to complete the creation of activity like
    // the view hierarchy
    super.onCreate(savedInstanceState)

    // recovering the instance state
    gameState = savedInstanceState?.getString(GAME_STATE_KEY)

    // set the user interface layout for this activity
    // the layout file is defined in the project res/layout/main_activity.xml file
    setContentView(R.layout.main_activity)

    // initialize member TextView so we can manipulate it later
    textView = findViewById(R.id.text_view)
}

// This callback is called only when there is a saved instance that is previously saved by using
// onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
// other state here, possibly usable after onStart() has completed.
// The savedInstanceState Bundle is same as the one used in onCreate().
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
    textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY)
}

// invoked when the activity may be temporarily destroyed, save the instance state here
override fun onSaveInstanceState(outState: Bundle?) {
    outState?.run {
        putString(GAME_STATE_KEY, gameState)
        putString(TEXT_VIEW_KEY, textView.text.toString())
    }
    // call superclass to save any view hierarchy
    super.onSaveInstanceState(outState)
}

除了定義 XML 文件宫蛆,然后將其傳遞給 [setContentView()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#setContentView(android.view.View))艘包,您還可以在 Activity 代碼中新建 [View](https://developer.android.google.cn/reference/android/view/View?hl=zh-cn) 對(duì)象,并將新建的 [View](https://developer.android.google.cn/reference/android/view/View?hl=zh-cn) 插入到 [ViewGroup](https://developer.android.google.cn/reference/android/view/ViewGroup?hl=zh-cn) 中耀盗,以構(gòu)建視圖層次結(jié)構(gòu)辑甜。然后,將根 [ViewGroup](https://developer.android.google.cn/reference/android/view/ViewGroup?hl=zh-cn) 傳遞給 [setContentView()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#setContentView(android.view.View)) 以使用該布局袍冷。如需詳細(xì)了解如何創(chuàng)建界面磷醋,請(qǐng)參閱界面文檔。

您的 Activity 并未處于“已創(chuàng)建”狀態(tài)胡诗。[onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle)) 方法完成執(zhí)行后邓线,Activity 進(jìn)入“已開始”狀態(tài)淌友,系統(tǒng)會(huì)相繼調(diào)用 [onStart()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStart())[onResume()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onResume()) 方法。下一部分將介紹 *[onStart()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStart())* 回調(diào)骇陈。

onStart()

當(dāng) Activity 進(jìn)入“已開始”狀態(tài)時(shí)震庭,系統(tǒng)會(huì)調(diào)用此回調(diào)。[onStart()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStart()) 調(diào)用使 Activity 對(duì)用戶可見你雌,因?yàn)閼?yīng)用會(huì)為 Activity 進(jìn)入前臺(tái)并支持互動(dòng)做準(zhǔn)備器联。例如,應(yīng)用通過(guò)此方法來(lái)初始化維護(hù)界面的代碼婿崭。

當(dāng) Activity 進(jìn)入已開始狀態(tài)時(shí)拨拓,與 Activity 生命周期相關(guān)聯(lián)的所有生命周期感知型組件都將收到 [ON_START](https://developer.android.google.cn/reference/androidx/lifecycle/Lifecycle.Event?hl=zh-cn#ON_START) 事件。

[onStart()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStart()) 方法會(huì)非趁フ唬快速地完成渣磷,并且與“已創(chuàng)建”狀態(tài)一樣,Activity 不會(huì)一直處于“已開始”狀態(tài)授瘦。一旦此回調(diào)結(jié)束醋界,Activity 便會(huì)進(jìn)入“已恢復(fù)”狀態(tài),系統(tǒng)將調(diào)用 [onResume()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onResume()) 方法提完。

onResume()

Activity 會(huì)在進(jìn)入“已恢復(fù)”狀態(tài)時(shí)來(lái)到前臺(tái)形纺,然后系統(tǒng)調(diào)用 [onResume()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onResume()) 回調(diào)。這是應(yīng)用與用戶互動(dòng)的狀態(tài)徒欣。應(yīng)用會(huì)一直保持這種狀態(tài)逐样,直到某些事件發(fā)生,讓焦點(diǎn)遠(yuǎn)離應(yīng)用帚称。此類事件包括接到來(lái)電、用戶導(dǎo)航到另一個(gè) Activity秽澳,或設(shè)備屏幕關(guān)閉闯睹。

當(dāng) Activity 進(jìn)入已恢復(fù)狀態(tài)時(shí),與 Activity 生命周期相關(guān)聯(lián)的所有生命周期感知型組件都將收到 [ON_RESUME](https://developer.android.google.cn/reference/androidx/lifecycle/Lifecycle.Event?hl=zh-cn#ON_RESUME) 事件担神。這時(shí)楼吃,生命周期組件可以啟用在組件可見且位于前臺(tái)時(shí)需要運(yùn)行的任何功能,例如啟動(dòng)相機(jī)預(yù)覽妄讯。

當(dāng)發(fā)生中斷事件時(shí)孩锡,Activity 進(jìn)入“已暫停”狀態(tài)亥贸,系統(tǒng)調(diào)用 [onPause()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onPause()) 回調(diào)躬窜。

如果 Activity 從“已暫停”狀態(tài)返回“已恢復(fù)”狀態(tài)炕置,系統(tǒng)將再次調(diào)用 [onResume()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onResume()) 方法荣挨。因此男韧,您應(yīng)實(shí)現(xiàn) [onResume()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onResume()),以初始化在 [onPause()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onPause()) 期間釋放的組件默垄,并執(zhí)行每次 Activity 進(jìn)入“已恢復(fù)”狀態(tài)時(shí)必須完成的任何其他初始化操作此虑。

以下是生命周期感知型組件的示例,該組件在收到 [ON_RESUME](https://developer.android.google.cn/reference/androidx/lifecycle/Lifecycle.Event?hl=zh-cn#ON_RESUME) 事件時(shí)訪問(wèn)相機(jī):

KotlinJava

<select><option value="">--</option><option value="javascript">javascript</option><option value="typescript">typescript</option><option value="bash">bash</option><option value="sql">sql</option><option value="json">json</option><option value="html">html</option><option value="css">css</option><option value="c">c</option><option value="cpp">cpp</option><option value="java">java</option><option value="ruby">ruby</option><option value="python">python</option><option value="go">go</option><option value="rust">rust</option><option value="markdown">markdown</option></select>

class CameraComponent : LifecycleObserver {

    ...

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun initializeCamera() {
        if (camera == null) {
            getCamera()
        }
    }

    ...
}

[LifecycleObserver](https://developer.android.google.cn/reference/androidx/lifecycle/LifecycleObserver?hl=zh-cn) 收到 ON_RESUME 事件后口锭,上述代碼便會(huì)初始化相機(jī)朦前。然而,在多窗口模式下鹃操,即使處于“已暫途麓纾”狀態(tài),您的 Activity 也可能完全可見组民。例如棒仍,當(dāng)用戶處于多窗口模式,并點(diǎn)按另一個(gè)不包含 Activity 的窗口時(shí)臭胜,您的 Activity 將進(jìn)入“已暫湍洌”狀態(tài)。如果您希望相機(jī)僅在應(yīng)用處于“已恢復(fù)”(可見且在前臺(tái)運(yùn)行)狀態(tài)時(shí)可用耸三,請(qǐng)?jiān)谑盏缴鲜?ON_RESUME 事件后初始化相機(jī)乱陡。如果您希望在 Activity 處于“已暫停”狀態(tài)但可見時(shí)(例如在多窗口模式下)保持相機(jī)可用仪壮,應(yīng)在收到 ON_START 事件后初始化相機(jī)憨颠。但請(qǐng)注意,若要讓相機(jī)在 Activity 處于“已暫突”狀態(tài)時(shí)可用爽彤,可能會(huì)導(dǎo)致系統(tǒng)在多窗口模式下拒絕其他處于“已恢復(fù)”狀態(tài)的應(yīng)用訪問(wèn)相機(jī)。有時(shí)可能有必要讓相機(jī)在 Activity 處于“已暫透肯荩”狀態(tài)時(shí)保持可用适篙,但這樣做實(shí)際可能會(huì)降低整體用戶體驗(yàn)。請(qǐng)仔細(xì)考慮箫爷,生命周期的哪個(gè)階段更適合在多窗口環(huán)境下控制共享系統(tǒng)資源嚷节。如需詳細(xì)了解如何支持多窗口模式,請(qǐng)參閱多窗口支持虎锚。

無(wú)論您選擇在哪個(gè)構(gòu)建事件中執(zhí)行初始化操作硫痰,都請(qǐng)務(wù)必使用相應(yīng)的生命周期事件來(lái)釋放資源。如果您在收到 ON_START 事件后初始化某些內(nèi)容窜护,請(qǐng)?jiān)谑盏?ON_STOP 事件后釋放或終止相應(yīng)內(nèi)容效斑。如果您在收到 ON_RESUME 事件后初始化某些內(nèi)容,請(qǐng)?jiān)谑盏?ON_PAUSE 事件后將其釋放柱徙。

請(qǐng)注意鳍悠,上述代碼段將相機(jī)初始化代碼放置在生命周期感知型組件中税娜。您也可以直接將此代碼放入 Activity 生命周期回調(diào)(例如 [onStart()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStart())[onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop())),但我們不建議您這樣做藏研。通過(guò)將此邏輯添加到獨(dú)立的生命周期感知型組件中敬矩,您可以對(duì)多個(gè) Activity 重復(fù)使用該組件,而無(wú)需復(fù)制代碼蠢挡。請(qǐng)參閱使用生命周期感知型組件處理生命周期弧岳,了解如何創(chuàng)建生命周期感知型組件。

onPause()

系統(tǒng)將此方法視為用戶將要離開您的 Activity 的第一個(gè)標(biāo)志(盡管這并不總是意味著 Activity 會(huì)被銷毀)业踏;此方法表示 Activity 不再位于前臺(tái)(盡管在用戶處于多窗口模式時(shí) Activity 仍然可見)禽炬。使用 [onPause()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onPause()) 方法暫停或調(diào)整當(dāng) [Activity](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn) 處于“已暫颓诩遥”狀態(tài)時(shí)不應(yīng)繼續(xù)(或應(yīng)有節(jié)制地繼續(xù))的操作腹尖,以及您希望很快恢復(fù)的操作。Activity 進(jìn)入此狀態(tài)的原因有很多伐脖。例如:

  • ?

    onResume() 部分所述热幔,某個(gè)事件會(huì)中斷應(yīng)用執(zhí)行。這是最常見的情況讼庇。

  • ?

    在 Android 7.0(API 級(jí)別 24)或更高版本中绎巨,有多個(gè)應(yīng)用在多窗口模式下運(yùn)行。無(wú)論何時(shí)蠕啄,都只有一個(gè)應(yīng)用(窗口)可以擁有焦點(diǎn)场勤,因此系統(tǒng)會(huì)暫停所有其他應(yīng)用。

  • ?

    有新的半透明 Activity(例如對(duì)話框)處于開啟狀態(tài)歼跟。只要 Activity 仍然部分可見但并未處于焦點(diǎn)之中和媳,它便會(huì)一直暫停。

當(dāng) Activity 進(jìn)入已暫停狀態(tài)時(shí)哈街,與 Activity 生命周期相關(guān)聯(lián)的所有生命周期感知型組件都將收到 [ON_PAUSE](https://developer.android.google.cn/reference/androidx/lifecycle/Lifecycle.Event?hl=zh-cn#ON_PAUSE) 事件留瞳。這時(shí),生命周期組件可以停止在組件未位于前臺(tái)時(shí)無(wú)需運(yùn)行的任何功能叹卷,例如停止相機(jī)預(yù)覽撼港。

您還可以使用 [onPause()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onPause()) 方法釋放系統(tǒng)資源坪它、傳感器(例如 GPS)手柄骤竹,或當(dāng)您的 Activity 暫停且用戶不需要它們時(shí)仍然可能影響電池續(xù)航時(shí)間的任何資源。然而往毡,正如上文的 onResume() 部分所述蒙揣,如果處于多窗口模式,“已暫涂t!钡?Activity 仍完全可見懒震。因此罩息,您應(yīng)該考慮使用 onStop() 而非 onPause() 來(lái)完全釋放或調(diào)整與界面相關(guān)的資源和操作,以便更好地支持多窗口模式个扰。

響應(yīng) ON_PAUSE 事件的以下 [LifecycleObserver](https://developer.android.google.cn/reference/androidx/lifecycle/LifecycleObserver?hl=zh-cn) 示例與上述 ON_RESUME 事件示例相對(duì)應(yīng)瓷炮,會(huì)釋放在收到 ON_RESUME 事件后初始化的相機(jī):

KotlinJava

<select><option value="">--</option><option value="javascript">javascript</option><option value="typescript">typescript</option><option value="bash">bash</option><option value="sql">sql</option><option value="json">json</option><option value="html">html</option><option value="css">css</option><option value="c">c</option><option value="cpp">cpp</option><option value="java">java</option><option value="ruby">ruby</option><option value="python">python</option><option value="go">go</option><option value="rust">rust</option><option value="markdown">markdown</option></select>

class CameraComponent : LifecycleObserver {

    ...

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun releaseCamera() {
        camera?.release()
        camera = null
    }

    ...
}

請(qǐng)注意,上述代碼段在 LifecycleObserver 收到 ON_PAUSE 事件后放置相機(jī)釋放代碼递宅。如前所述娘香,請(qǐng)參閱使用生命周期感知型組件處理生命周期了解如何創(chuàng)建生命周期感知型組件。

[onPause()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onPause()) 執(zhí)行非常簡(jiǎn)單办龄,而且不一定要有足夠的時(shí)間來(lái)執(zhí)行保存操作烘绽。因此,您應(yīng)使用 [onPause()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onPause()) 來(lái)保存應(yīng)用或用戶數(shù)據(jù)俐填、進(jìn)行網(wǎng)絡(luò)調(diào)用或執(zhí)行數(shù)據(jù)庫(kù)事務(wù)安接。因?yàn)樵谠摲椒ㄍ瓿芍埃祟惞ぷ骺赡軣o(wú)法完成英融。相反盏檐,您應(yīng)在 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 期間執(zhí)行高負(fù)載的關(guān)閉操作。如需詳細(xì)了解在 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 期間執(zhí)行的合適操作矢赁,請(qǐng)參閱 onStop()糯笙。如需詳細(xì)了解如何保存數(shù)據(jù),請(qǐng)參閱保存和恢復(fù) Activity 狀態(tài)撩银。

[onPause()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onPause()) 方法的完成并不意味著 Activity 離開“已暫透椋”狀態(tài)。相反额获,Activity 會(huì)保持此狀態(tài)够庙,直到其恢復(fù)或變成對(duì)用戶完全不可見。如果 Activity 恢復(fù)抄邀,系統(tǒng)將再次調(diào)用 [onResume()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onResume()) 回調(diào)耘眨。如果 Activity 從“已暫停”狀態(tài)返回“已恢復(fù)”狀態(tài)境肾,系統(tǒng)會(huì)讓 [Activity](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn) 實(shí)例繼續(xù)駐留在內(nèi)存中剔难,并會(huì)在系統(tǒng)調(diào)用 [onResume()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onResume()) 時(shí)重新調(diào)用該實(shí)例。在這種情況下奥喻,您無(wú)需重新初始化在任何回調(diào)方法導(dǎo)致 Activity 進(jìn)入“已恢復(fù)”狀態(tài)期間創(chuàng)建的組件偶宫。如果 Activity 變?yōu)橥耆豢梢姡到y(tǒng)會(huì)調(diào)用 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop())环鲤。下一部分將介紹 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 回調(diào)纯趋。

onStop()

如果您的 Activity 不再對(duì)用戶可見,說(shuō)明其已進(jìn)入“已停止”狀態(tài),因此系統(tǒng)將調(diào)用 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 回調(diào)吵冒。例如纯命,當(dāng)新啟動(dòng)的 Activity 覆蓋整個(gè)屏幕時(shí),可能會(huì)發(fā)生這種情況痹栖。如果 Activity 已結(jié)束運(yùn)行并即將終止亿汞,系統(tǒng)還可以調(diào)用 *[onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop())*

當(dāng) Activity 進(jìn)入已停止?fàn)顟B(tài)時(shí)揪阿,與 Activity 生命周期相關(guān)聯(lián)的所有生命周期感知型組件都將收到 [ON_STOP](https://developer.android.google.cn/reference/androidx/lifecycle/Lifecycle.Event?hl=zh-cn#ON_STOP) 事件留夜。這時(shí),生命周期組件可以停止在組件未顯示在屏幕上時(shí)無(wú)需運(yùn)行的任何功能图甜。

[onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 方法中碍粥,應(yīng)用應(yīng)釋放或調(diào)整在應(yīng)用對(duì)用戶不可見時(shí)的無(wú)用資源。例如黑毅,應(yīng)用可以暫停動(dòng)畫效果嚼摩,或從精確位置更新切換到粗略位置更新。使用 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 而非 [onPause()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onPause()) 可確保與界面相關(guān)的工作繼續(xù)進(jìn)行矿瘦,即使用戶在多窗口模式下查看您的 Activity 也能如此枕面。

您還應(yīng)使用 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 執(zhí)行 CPU 相對(duì)密集的關(guān)閉操作。例如缚去,如果您無(wú)法找到更合適的時(shí)機(jī)來(lái)將信息保存到數(shù)據(jù)庫(kù)潮秘,可以在 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 期間執(zhí)行此操作。以下示例展示了 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 的實(shí)現(xiàn)易结,它將草稿筆記內(nèi)容保存到持久性存儲(chǔ)空間中:

KotlinJava

<select><option value="">--</option><option value="javascript">javascript</option><option value="typescript">typescript</option><option value="bash">bash</option><option value="sql">sql</option><option value="json">json</option><option value="html">html</option><option value="css">css</option><option value="c">c</option><option value="cpp">cpp</option><option value="java">java</option><option value="ruby">ruby</option><option value="python">python</option><option value="go">go</option><option value="rust">rust</option><option value="markdown">markdown</option></select>

override fun onStop() {
    // call the superclass method first
    super.onStop()

    // save the note's current draft, because the activity is stopping
    // and we want to be sure the current note progress isn't lost.
    val values = ContentValues().apply {
        put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText())
        put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle())
    }

    // do this update in background on an AsyncQueryHandler or equivalent
    asyncQueryHandler.startUpdate(
            token,     // int token to correlate calls
            null,      // cookie, not used here
            uri,       // The URI for the note to update.
            values,    // The map of column names and new values to apply to them.
            null,      // No SELECT criteria are used.
            null       // No WHERE columns are used.
    )
}

請(qǐng)注意枕荞,上述代碼示例直接使用 SQLite。但您應(yīng)該改用 Room搞动,這是一個(gè)通過(guò) SQLite 提供抽象層的持久性庫(kù)躏精。如需詳細(xì)了解使用 Room 的好處,以及如何在應(yīng)用中實(shí)現(xiàn) Room鹦肿,請(qǐng)參閱 Room 持久性庫(kù)指南矗烛。

當(dāng)您的 Activity 進(jìn)入“已停止”狀態(tài)時(shí),[Activity](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn) 對(duì)象會(huì)繼續(xù)駐留在內(nèi)存中:該對(duì)象將維護(hù)所有狀態(tài)和成員信息箩溃,但不會(huì)附加到窗口管理器瞭吃。Activity 恢復(fù)后,Activity 會(huì)重新調(diào)用這些信息涣旨。您無(wú)需重新初始化在任何回調(diào)方法導(dǎo)致 Activity 進(jìn)入“已恢復(fù)”狀態(tài)期間創(chuàng)建的組件歪架。系統(tǒng)還會(huì)追蹤布局中每個(gè) [View](https://developer.android.google.cn/reference/android/view/View?hl=zh-cn) 對(duì)象的當(dāng)前狀態(tài),如果用戶在 [EditText](https://developer.android.google.cn/reference/android/widget/EditText?hl=zh-cn) 微件中輸入文本开泽,系統(tǒng)將保留文本內(nèi)容牡拇,因此您無(wú)需保存和恢復(fù)文本魁瞪。

注意:Activity 停止后穆律,如果系統(tǒng)需要恢復(fù)內(nèi)存惠呼,可能會(huì)銷毀包含該 Activity 的進(jìn)程。即使系統(tǒng)在 Activity 停止后銷毀相應(yīng)進(jìn)程峦耘,系統(tǒng)仍會(huì)保留 [Bundle](https://developer.android.google.cn/reference/android/os/Bundle?hl=zh-cn)(鍵值對(duì)的 blob)中 [View](https://developer.android.google.cn/reference/android/view/View?hl=zh-cn) 對(duì)象(例如 [EditText](https://developer.android.google.cn/reference/android/widget/EditText?hl=zh-cn) 微件中的文本)的狀態(tài)剔蹋,并在用戶返回 Activity 時(shí)恢復(fù)這些對(duì)象。如需詳細(xì)了解如何恢復(fù)用戶返回的 Activity辅髓,請(qǐng)參閱保存和恢復(fù) Activity 狀態(tài)泣崩。

進(jìn)入“已停止”狀態(tài)后,Activity 要么返回與用戶互動(dòng)洛口,要么結(jié)束運(yùn)行并消失矫付。如果 Activity 返回,系統(tǒng)將調(diào)用 [onRestart()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onRestart())第焰。如果 [Activity](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn) 結(jié)束運(yùn)行买优,系統(tǒng)將調(diào)用 [onDestroy()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onDestroy())。下一部分將介紹 [onDestroy()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onDestroy()) 回調(diào)挺举。

onDestroy()

銷毀 Activity 之前杀赢,系統(tǒng)會(huì)先調(diào)用 [onDestroy()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onDestroy())。系統(tǒng)調(diào)用此回調(diào)的原因如下:

    Activity 即將結(jié)束(由于用戶徹底關(guān)閉 Activity 或由于系統(tǒng)為 Activity 調(diào)用 [finish()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#finish()))湘纵,或者

    由于配置變更(例如設(shè)備旋轉(zhuǎn)或多窗口模式)脂崔,系統(tǒng)暫時(shí)銷毀 Activity

當(dāng) Activity 進(jìn)入已銷毀狀態(tài)時(shí),與 Activity 生命周期相關(guān)聯(lián)的所有生命周期感知型組件都將收到 [ON_DESTROY](https://developer.android.google.cn/reference/androidx/lifecycle/Lifecycle.Event?hl=zh-cn#ON_DESTROY) 事件梧喷。這時(shí)砌左,生命周期組件可以在 Activity 被銷毀之前清理所需的任何數(shù)據(jù)。

您應(yīng)使用 [ViewModel](https://developer.android.google.cn/reference/androidx/lifecycle/ViewModel?hl=zh-cn) 對(duì)象來(lái)包含 Activity 的相關(guān)視圖數(shù)據(jù)铺敌,而不是在您的 Activity 中加入邏輯來(lái)確定 Activity 被銷毀的原因绊困。如果因配置變更而重新創(chuàng)建 Activity,ViewModel 不必執(zhí)行任何操作适刀,因?yàn)橄到y(tǒng)將保留 ViewModel 并將其提供給下一個(gè) Activity 實(shí)例秤朗。如果不重新創(chuàng)建 Activity,ViewModel 將調(diào)用 [onCleared()](https://developer.android.google.cn/reference/androidx/lifecycle/ViewModel?hl=zh-cn#onCleared()) 方法笔喉,以便在 Activity 被銷毀前清除所需的任何數(shù)據(jù)取视。

您可以使用 [isFinishing()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#isFinishing()) 方法區(qū)分這兩種情況。

如果 Activity 即將結(jié)束常挚,onDestroy() 是 Activity 收到的最后一個(gè)生命周期回調(diào)作谭。如果由于配置變更而調(diào)用 onDestroy(),系統(tǒng)會(huì)立即新建 Activity 實(shí)例奄毡,然后在新配置中為新實(shí)例調(diào)用 [onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle))折欠。

[onDestroy()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onDestroy()) 回調(diào)應(yīng)釋放先前的回調(diào)(例如 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()))尚未釋放的所有資源。

Activity 狀態(tài)和從內(nèi)存中彈出

系統(tǒng)會(huì)在需要釋放 RAM 時(shí)終止進(jìn)程;系統(tǒng)終止給定進(jìn)程的可能性取決于當(dāng)時(shí)進(jìn)程的狀態(tài)锐秦。反之咪奖,進(jìn)程狀態(tài)取決于在進(jìn)程中運(yùn)行的 Activity 的狀態(tài)。表 1 展示了進(jìn)程狀態(tài)酱床、Activity 狀態(tài)以及系統(tǒng)終止進(jìn)程的可能性之間的關(guān)系羊赵。

|

系統(tǒng)終止進(jìn)程的可能性

|

進(jìn)程狀態(tài)

|

Activity 狀態(tài)

|
|

較小

|

前臺(tái)(擁有或即將獲得焦點(diǎn))

|

已創(chuàng)建 已開始 已恢復(fù)

|
|

較大

|

后臺(tái)(失去焦點(diǎn))

|

已暫停

|
|

最大

|

后臺(tái)(不可見)

|

已停止

|
|

|

已銷毀

| |

表 1. 進(jìn)程生命周期和 Activity 狀態(tài)之間的關(guān)系

系統(tǒng)永遠(yuǎn)不會(huì)直接終止 Activity 以釋放內(nèi)存,而是會(huì)終止 Activity 所在的進(jìn)程扇谣。系統(tǒng)不僅會(huì)銷毀 Activity昧捷,還會(huì)銷毀在該進(jìn)程中運(yùn)行的所有其他內(nèi)容。如需了解如何在系統(tǒng)啟動(dòng)的進(jìn)程被終止時(shí)保留和恢復(fù) Activity 的界面狀態(tài)罐寨,請(qǐng)參閱保存和恢復(fù) Activity 狀態(tài)靡挥。

用戶還可以使用“設(shè)置”下的“應(yīng)用管理器”來(lái)終止進(jìn)程,以終止相應(yīng)的應(yīng)用鸯绿。

如需詳細(xì)了解一般進(jìn)程芹血,請(qǐng)參閱進(jìn)程和線程。如需詳細(xì)了解進(jìn)程生命周期如何與其中 Activity 的狀態(tài)相關(guān)聯(lián)楞慈,請(qǐng)參閱相應(yīng)頁(yè)面的進(jìn)程生命周期部分幔烛。

保存和恢復(fù)瞬時(shí)界面狀態(tài)

用戶期望 Activity 的界面狀態(tài)在整個(gè)配置變更(例如旋轉(zhuǎn)或切換到多窗口模式)期間保持不變。但是囊蓝,默認(rèn)情況下饿悬,系統(tǒng)會(huì)在發(fā)生此類配置更改時(shí)銷毀 Activity,從而清除存儲(chǔ)在 Activity 實(shí)例中的任何界面狀態(tài)聚霜。同樣狡恬,如果用戶暫時(shí)從您的應(yīng)用切換到其他應(yīng)用,并在稍后返回您的應(yīng)用蝎宇,他們也希望界面狀態(tài)保持不變弟劲。但是,當(dāng)用戶離開應(yīng)用且您的 Activity 停止時(shí)姥芥,系統(tǒng)可能會(huì)銷毀該應(yīng)用的進(jìn)程兔乞。

當(dāng) Activity 因系統(tǒng)限制而被銷毀時(shí),您應(yīng)組合使用 [ViewModel](https://developer.android.google.cn/reference/androidx/lifecycle/ViewModel?hl=zh-cn)凉唐、[onSaveInstanceState()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onSaveInstanceState(android.os.Bundle)) 和/或本地存儲(chǔ)來(lái)保留用戶的瞬時(shí)界面狀態(tài)庸追。如需詳細(xì)了解用戶期望與系統(tǒng)行為,以及如何在系統(tǒng)啟動(dòng)的 Activity 和進(jìn)程被終止后最大程度地保留復(fù)雜的界面狀態(tài)數(shù)據(jù)台囱,請(qǐng)參閱保存界面狀態(tài)淡溯。

本部分概述了實(shí)例狀態(tài)的定義,以及如何實(shí)現(xiàn) onSaveInstance() 方法簿训,該方法是對(duì) Activity 本身的回調(diào)咱娶。如果界面數(shù)據(jù)簡(jiǎn)單且輕量米间,例如原始數(shù)據(jù)類型或簡(jiǎn)單對(duì)象(比如 String),您可以單獨(dú)使用 onSaveInstanceState() 使界面狀態(tài)在配置更改和系統(tǒng)啟動(dòng)的進(jìn)程被終止時(shí)保持不變膘侮。但在大多數(shù)情況下屈糊,您應(yīng)使用 ViewModel 和 onSaveInstanceState()(如 保存界面狀態(tài)中所述),因?yàn)?onSaveInstanceState() 會(huì)產(chǎn)生序列化/反序列化費(fèi)用喻喳。

實(shí)例狀態(tài)

在某些情況下,您的 Activity 會(huì)因正常的應(yīng)用行為而被銷毀困曙,例如當(dāng)用戶按下返回按鈕或您的 Activity 通過(guò)調(diào)用 [finish()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#finish()) 方法發(fā)出銷毀信號(hào)時(shí)表伦。當(dāng)您的 Activity 因用戶按下返回按鈕或因其自行結(jié)束而被銷毀時(shí),系統(tǒng)和用戶對(duì)該 [Activity](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn) 實(shí)例的概念將永遠(yuǎn)消失慷丽。在這些情況下蹦哼,用戶的期望與系統(tǒng)行為相匹配,您無(wú)需完成任何額外工作要糊。

但是纲熏,如果系統(tǒng)因系統(tǒng)限制(例如配置變更或內(nèi)存壓力)而銷毀 Activity,雖然實(shí)際的 [Activity](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn) 實(shí)例會(huì)消失锄俄,但系統(tǒng)會(huì)記住它曾經(jīng)存在過(guò)局劲。如果用戶嘗試回退到該 Activity,系統(tǒng)將使用一組描述 Activity 銷毀時(shí)狀態(tài)的已保存數(shù)據(jù)新建該 Activity 的實(shí)例奶赠。

系統(tǒng)用于恢復(fù)先前狀態(tài)的已保存數(shù)據(jù)稱為實(shí)例狀態(tài)鱼填,是存儲(chǔ)在 [Bundle](https://developer.android.google.cn/reference/android/os/Bundle?hl=zh-cn) 對(duì)象中的鍵值對(duì)集合。默認(rèn)情況下毅戈,系統(tǒng)使用 *[Bundle](https://developer.android.google.cn/reference/android/os/Bundle?hl=zh-cn)* 實(shí)例狀態(tài)來(lái)保存 Activity 布局中每個(gè) *[View](https://developer.android.google.cn/reference/android/view/View?hl=zh-cn)* 對(duì)象的相關(guān)信息(例如在 *[EditText](https://developer.android.google.cn/reference/android/widget/EditText?hl=zh-cn)* 微件中輸入的文本值)苹丸。這樣,如果您的 Activity 實(shí)例被銷毀并重新創(chuàng)建苇经,布局狀態(tài)便會(huì)恢復(fù)為其先前的狀態(tài)赘理,且您無(wú)需編寫代碼埂陆。但是鞠呈,您的 Activity 可能包含您要恢復(fù)的更多狀態(tài)信息,例如追蹤用戶在 Activity 中的進(jìn)程的成員變量厦幅。

注意:為了使 Android 系統(tǒng)恢復(fù) Activity 中視圖的狀態(tài)蜘澜,每個(gè)視圖必須具有 android:id 屬性提供的唯一 ID阻桅。

[Bundle](https://developer.android.google.cn/reference/android/os/Bundle?hl=zh-cn) 對(duì)象并不適合保留大量數(shù)據(jù),因?yàn)樗枰谥骶€程上進(jìn)行序列化處理并占用系統(tǒng)進(jìn)程內(nèi)存兼都。如需保存大量數(shù)據(jù)嫂沉,您應(yīng)組合使用持久性本地存儲(chǔ)、[onSaveInstanceState()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onSaveInstanceState(android.os.Bundle)) 方法和 [ViewModel](https://developer.android.google.cn/reference/androidx/lifecycle/ViewModel?hl=zh-cn) 類來(lái)保存數(shù)據(jù)扮碧,正如保存界面狀態(tài)中所述趟章。

使用 onSaveInstanceState() 保存簡(jiǎn)單輕量的界面狀態(tài)

當(dāng)您的 Activity 開始停止時(shí)杏糙,系統(tǒng)會(huì)調(diào)用 [onSaveInstanceState()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onSaveInstanceState(android.os.Bundle)) 方法,以便您的 Activity 可以將狀態(tài)信息保存到實(shí)例狀態(tài) Bundle 中蚓土。此方法的默認(rèn)實(shí)現(xiàn)保存有關(guān) Activity 視圖層次結(jié)構(gòu)狀態(tài)的瞬時(shí)信息宏侍,例如 [EditText](https://developer.android.google.cn/reference/android/widget/EditText?hl=zh-cn) 微件中的文本或 [ListView](https://developer.android.google.cn/reference/android/widget/ListView?hl=zh-cn) 微件的滾動(dòng)位置。

如需保存 Activity 的其他實(shí)例狀態(tài)信息蜀漆,您必須替換 [onSaveInstanceState()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onSaveInstanceState(android.os.Bundle))谅河,并將鍵值對(duì)添加到您的 Activity 意外銷毀時(shí)事件中所保存的 [Bundle](https://developer.android.google.cn/reference/android/os/Bundle?hl=zh-cn) 對(duì)象中。替換 onSaveInstanceState() 時(shí)确丢,如果您希望默認(rèn)實(shí)現(xiàn)保存視圖層次結(jié)構(gòu)的狀態(tài)绷耍,必須調(diào)用父類實(shí)現(xiàn)。例如:

KotlinJava

<select><option value="">--</option><option value="javascript">javascript</option><option value="typescript">typescript</option><option value="bash">bash</option><option value="sql">sql</option><option value="json">json</option><option value="html">html</option><option value="css">css</option><option value="c">c</option><option value="cpp">cpp</option><option value="java">java</option><option value="ruby">ruby</option><option value="python">python</option><option value="go">go</option><option value="rust">rust</option><option value="markdown">markdown</option></select>

override fun onSaveInstanceState(outState: Bundle?) {
    // Save the user's current game state
    outState?.run {
        putInt(STATE_SCORE, currentScore)
        putInt(STATE_LEVEL, currentLevel)
    }

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(outState)
}

companion object {
    val STATE_SCORE = "playerScore"
    val STATE_LEVEL = "playerLevel"
}

注意:當(dāng)用戶顯式關(guān)閉 Activity 時(shí)鲜侥,或者在其他情況下調(diào)用 finish() 時(shí)褂始,系統(tǒng)不會(huì)調(diào)用 [onSaveInstanceState()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onSaveInstanceState(android.os.Bundle))

如需保存持久性數(shù)據(jù)(例如用戶首選項(xiàng)或數(shù)據(jù)庫(kù)中的數(shù)據(jù))描函,您應(yīng)在 Activity 位于前臺(tái)時(shí)抓住合適機(jī)會(huì)崎苗。如果沒有這樣的時(shí)機(jī),您應(yīng)在執(zhí)行 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 方法期間保存此類數(shù)據(jù)舀寓。

使用保存的實(shí)例狀態(tài)恢復(fù) Activity 界面狀態(tài)

重建先前被銷毀的 Activity 后胆数,您可以從系統(tǒng)傳遞給 Activity 的 [Bundle](https://developer.android.google.cn/reference/android/os/Bundle?hl=zh-cn) 中恢復(fù)保存的實(shí)例狀態(tài)。[onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle))[onRestoreInstanceState()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onRestoreInstanceState(android.os.Bundle)) 回調(diào)方法均會(huì)收到包含實(shí)例狀態(tài)信息的相同 [Bundle](https://developer.android.google.cn/reference/android/os/Bundle?hl=zh-cn)互墓。

因?yàn)闊o(wú)論系統(tǒng)是新建 Activity 實(shí)例還是重新創(chuàng)建之前的實(shí)例幅慌,都會(huì)調(diào)用 [onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle)) 方法,所以在嘗試讀取之前轰豆,您必須檢查狀態(tài) Bundle 是否為 null胰伍。如果為 null,系統(tǒng)將新建 Activity 實(shí)例酸休,而不會(huì)恢復(fù)之前銷毀的實(shí)例骂租。

例如,以下代碼段顯示如何在 [onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle)) 中恢復(fù)某些狀態(tài)數(shù)據(jù):

KotlinJava

<select><option value="">--</option><option value="javascript">javascript</option><option value="typescript">typescript</option><option value="bash">bash</option><option value="sql">sql</option><option value="json">json</option><option value="html">html</option><option value="css">css</option><option value="c">c</option><option value="cpp">cpp</option><option value="java">java</option><option value="ruby">ruby</option><option value="python">python</option><option value="go">go</option><option value="rust">rust</option><option value="markdown">markdown</option></select>

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState) // Always call the superclass first

    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        with(savedInstanceState) {
            // Restore value of members from saved state
            currentScore = getInt(STATE_SCORE)
            currentLevel = getInt(STATE_LEVEL)
        }
    } else {
        // Probably initialize members with default values for a new instance
    }
    // ...
}

您可以選擇實(shí)現(xiàn)系統(tǒng)在 [onStart()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStart()) 方法之后調(diào)用的 [onRestoreInstanceState()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onRestoreInstanceState(android.os.Bundle))斑司,而不是在 [onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle)) 期間恢復(fù)狀態(tài)渗饮。僅當(dāng)存在要恢復(fù)的已保存狀態(tài)時(shí),系統(tǒng)才會(huì)調(diào)用 [onRestoreInstanceState()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onRestoreInstanceState(android.os.Bundle))宿刮,因此您無(wú)需檢查 [Bundle](https://developer.android.google.cn/reference/android/os/Bundle?hl=zh-cn) 是否為 null:

KotlinJava

<select><option value="">--</option><option value="javascript">javascript</option><option value="typescript">typescript</option><option value="bash">bash</option><option value="sql">sql</option><option value="json">json</option><option value="html">html</option><option value="css">css</option><option value="c">c</option><option value="cpp">cpp</option><option value="java">java</option><option value="ruby">ruby</option><option value="python">python</option><option value="go">go</option><option value="rust">rust</option><option value="markdown">markdown</option></select>

override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState)

    // Restore state members from saved instance
    savedInstanceState?.run {
        currentScore = getInt(STATE_SCORE)
        currentLevel = getInt(STATE_LEVEL)
    }
}

注意:您應(yīng)始終調(diào)用 [onRestoreInstanceState()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onRestoreInstanceState(android.os.Bundle)) 的父類實(shí)現(xiàn)互站,以便默認(rèn)實(shí)現(xiàn)可以恢復(fù)視圖層次結(jié)構(gòu)的狀態(tài)。

在 Activity 之間導(dǎo)航

在應(yīng)用的生命周期中僵缺,應(yīng)用很可能會(huì)多次進(jìn)入和退出 Activity胡桃。例如,用戶可以點(diǎn)按設(shè)備的返回按鈕磕潮,或者 Activity 可能需要啟動(dòng)不同的 Activity翠胰。本部分介紹了實(shí)現(xiàn)成功的 Activity 轉(zhuǎn)換需要了解的主題容贝。這些主題包括從另一個(gè) Activity 啟動(dòng) Activity、保存 Activity 狀態(tài)之景,以及恢復(fù) Activity 狀態(tài)斤富。

從一個(gè) Activity 啟動(dòng)另一個(gè) Activity

Activity 通常需要在某個(gè)時(shí)刻啟動(dòng)另一個(gè) Activity。例如锻狗,當(dāng)應(yīng)用需要從當(dāng)前屏幕移動(dòng)到新屏幕時(shí)满力,就會(huì)出現(xiàn)這種需求。

根據(jù)您的 Activity 是否希望從即將啟動(dòng)的新 Activity 中獲取返回結(jié)果轻纪,您可以使用 [startActivity()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#startActivity(android.content.Intent,%20android.os.Bundle))[startActivityForResult()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#startActivityForResult(android.content.Intent,%20int)) 方法啟動(dòng)新 Activity油额。這兩種方法都需要傳入一個(gè) [Intent](https://developer.android.google.cn/reference/android/content/Intent?hl=zh-cn) 對(duì)象。

[Intent](https://developer.android.google.cn/reference/android/content/Intent?hl=zh-cn) 對(duì)象指定您要啟動(dòng)的具體 Activity桐磁,或描述您要執(zhí)行的操作類型(系統(tǒng)為您選擇相應(yīng)的 Activity悔耘,該 Activity 甚至可以來(lái)自不同應(yīng)用)讲岁。[Intent](https://developer.android.google.cn/reference/android/content/Intent?hl=zh-cn) 對(duì)象還可以攜帶由已啟動(dòng)的 Activity 使用的少量數(shù)據(jù)我擂。如需詳細(xì)了解 [Intent](https://developer.android.google.cn/reference/android/content/Intent?hl=zh-cn) 類,請(qǐng)參閱 Intent 和 Intent 過(guò)濾器缓艳。

startActivity()

如果新啟動(dòng)的 Activity 不需要返回結(jié)果校摩,當(dāng)前 Activity 可以通過(guò)調(diào)用 [startActivity()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#startActivity(android.content.Intent,%20android.os.Bundle)) 方法來(lái)啟動(dòng)它。

在自己的應(yīng)用中工作時(shí)阶淘,您通常只需啟動(dòng)已知 Activity衙吩。例如,以下代碼段顯示如何啟動(dòng)一個(gè)名為 SignInActivity 的 Activity溪窒。

KotlinJava

<select><option value="">--</option><option value="javascript">javascript</option><option value="typescript">typescript</option><option value="bash">bash</option><option value="sql">sql</option><option value="json">json</option><option value="html">html</option><option value="css">css</option><option value="c">c</option><option value="cpp">cpp</option><option value="java">java</option><option value="ruby">ruby</option><option value="python">python</option><option value="go">go</option><option value="rust">rust</option><option value="markdown">markdown</option></select>

val intent = Intent(this, SignInActivity::class.java)
startActivity(intent)

您的應(yīng)用可能還希望使用 Activity 中的數(shù)據(jù)執(zhí)行某些操作坤塞,例如發(fā)送電子郵件、短信或狀態(tài)更新澈蚌。在這種情況下摹芙,您的應(yīng)用自身可能不具有執(zhí)行此類操作所需的 Activity,因此您可以改為利用設(shè)備上其他應(yīng)用提供的 Activity 為您執(zhí)行這些操作宛瞄。這便是 intent 的真正價(jià)值所在浮禾。您可以創(chuàng)建一個(gè) intent,對(duì)您想執(zhí)行的操作進(jìn)行描述份汗,系統(tǒng)會(huì)從其他應(yīng)用啟動(dòng)相應(yīng)的 Activity盈电。如果有多個(gè) Activity 可以處理 intent,用戶可以選擇要使用哪一個(gè)杯活。例如匆帚,如果您想允許用戶發(fā)送電子郵件,可以創(chuàng)建以下 intent:

KotlinJava

<select><option value="">--</option><option value="javascript">javascript</option><option value="typescript">typescript</option><option value="bash">bash</option><option value="sql">sql</option><option value="json">json</option><option value="html">html</option><option value="css">css</option><option value="c">c</option><option value="cpp">cpp</option><option value="java">java</option><option value="ruby">ruby</option><option value="python">python</option><option value="go">go</option><option value="rust">rust</option><option value="markdown">markdown</option></select>

val intent = Intent(Intent.ACTION_SEND).apply {
    putExtra(Intent.EXTRA_EMAIL, recipientArray)
}
startActivity(intent)

添加到 intent 中的 EXTRA_EMAIL extra 是一個(gè)字符串?dāng)?shù)組旁钧,其中包含電子郵件的收件人電子郵件地址卷扮。當(dāng)電子郵件應(yīng)用響應(yīng)此 intent 時(shí)荡澎,該應(yīng)用會(huì)讀取 extra 中提供的字符串?dāng)?shù)組,并將該數(shù)組放入電子郵件撰寫表單的“收件人”字段晤锹。在這種情況下摩幔,電子郵件應(yīng)用的 Activity 會(huì)啟動(dòng),并且當(dāng)用戶完成操作時(shí)鞭铆,您的 Activity 會(huì)繼續(xù)運(yùn)行或衡。

startActivityForResult()

有時(shí),您會(huì)希望在 Activity 結(jié)束時(shí)從 Activity 中獲取返回結(jié)果车遂。例如封断,您可以啟動(dòng)一項(xiàng) Activity,讓用戶在聯(lián)系人列表中選擇收件人舶担;當(dāng) Activity 結(jié)束時(shí)坡疼,系統(tǒng)將返回用戶選擇的收件人。為此衣陶,您可以調(diào)用 [startActivityForResult(Intent, int)](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#startActivityForResult(android.content.Intent,%20int)) 方法柄瑰,其中整數(shù)參數(shù)會(huì)標(biāo)識(shí)該調(diào)用。此標(biāo)識(shí)符用于消除來(lái)自同一 Activity 的多次 [startActivityForResult(Intent, int)](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#startActivityForResult(android.content.Intent,%20int)) 調(diào)用之間的歧義剪况。這不是全局標(biāo)識(shí)符教沾,不存在與其他應(yīng)用或 Activity 沖突的風(fēng)險(xiǎn)。結(jié)果通過(guò) [onActivityResult(int, int, Intent)](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onActivityResult(int,%20int,%20android.content.Intent)) 方法返回译断。

當(dāng)子級(jí) Activity 退出時(shí)授翻,它可以調(diào)用 setResult(int) 將數(shù)據(jù)返回到其父級(jí)。子級(jí) Activity 必須始終提供結(jié)果代碼孙咪,該結(jié)果代碼可以是標(biāo)準(zhǔn)結(jié)果 RESULT_CANCELED堪唐、RESULT_OK,也可以是從 RESULT_FIRST_USER 開始的任何自定義值翎蹈。此外淮菠,子級(jí) Activity 可以根據(jù)需要返回包含它所需的任何其他數(shù)據(jù)的 [Intent](https://developer.android.google.cn/reference/android/content/Intent?hl=zh-cn) 對(duì)象。父級(jí) Activity 使用 [onActivityResult(int, int, Intent)](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onActivityResult(int,%20int,%20android.content.Intent)) 方法杨蛋,以及父級(jí) Activity 最初提供的整數(shù)標(biāo)識(shí)符來(lái)接收信息兜材。

如果子級(jí) Activity 由于任何原因(例如崩潰)而失敗,父級(jí) Activity 將收到代碼為 RESULT_CANCELED 的結(jié)果逞力。

KotlinJava

<select><option value="">--</option><option value="javascript">javascript</option><option value="typescript">typescript</option><option value="bash">bash</option><option value="sql">sql</option><option value="json">json</option><option value="html">html</option><option value="css">css</option><option value="c">c</option><option value="cpp">cpp</option><option value="java">java</option><option value="ruby">ruby</option><option value="python">python</option><option value="go">go</option><option value="rust">rust</option><option value="markdown">markdown</option></select>

class MyActivity : Activity() {
    // ...

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
            // When the user center presses, let them pick a contact.
            startActivityForResult(
                    Intent(Intent.ACTION_PICK,Uri.parse("content://contacts")),
                    PICK_CONTACT_REQUEST)
            return true
        }
        return false
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
        when (requestCode) {
            PICK_CONTACT_REQUEST ->
                if (resultCode == RESULT_OK) {
                    startActivity(Intent(Intent.ACTION_VIEW, intent?.data))
                }
        }
    }

    companion object {
        internal val PICK_CONTACT_REQUEST = 0
    }
}

協(xié)調(diào) Activity

當(dāng)一個(gè) Activity 啟動(dòng)另一個(gè) Activity 時(shí)曙寡,它們都會(huì)經(jīng)歷生命周期轉(zhuǎn)換。第一個(gè) Activity 停止運(yùn)行并進(jìn)入“已暫涂苡”或“已停止”狀態(tài)举庶,同時(shí)創(chuàng)建另一個(gè) Activity。如果這些 Activity 共享保存到磁盤或其他位置的數(shù)據(jù)揩抡,必須要明確第一個(gè) Activity 在創(chuàng)建第二個(gè) Activity 之前并未完全停止户侥。相反镀琉,啟動(dòng)第二個(gè) Activity 的過(guò)程與停止第一個(gè) Activity 的過(guò)程重疊。

生命周期回調(diào)的順序已有明確定義,特別是當(dāng)兩個(gè) Activity 在同一個(gè)進(jìn)程(應(yīng)用)中钓试,并且其中一個(gè)要啟動(dòng)另一個(gè)時(shí)。以下是 Activity A 啟動(dòng) Activity B 時(shí)的操作發(fā)生順序:

    Activity A 的 [onPause()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onPause()) 方法執(zhí)行糠睡。

    Activity B 的 [onCreate()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onCreate(android.os.Bundle))狮杨、[onStart()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStart())[onResume()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onResume()) 方法依次執(zhí)行(Activity B 現(xiàn)在具有用戶焦點(diǎn))。

    然后,如果 Activity A 在屏幕上不再顯示喂链,其 [onStop()](https://developer.android.google.cn/reference/android/app/Activity?hl=zh-cn#onStop()) 方法執(zhí)行迟杂。

您可以利用這種可預(yù)測(cè)的生命周期回調(diào)順序管理從一個(gè) Activity 到另一個(gè) Activity 的信息轉(zhuǎn)換火架。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末傍睹,一起剝皮案震驚了整個(gè)濱河市龙亲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摸吠,老刑警劉巖丛楚,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舶替,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)犬钢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人郑什,你說(shuō)我怎么就攤上這事⌒眩” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)吗浩。 經(jīng)常有香客問(wèn)我,道長(zhǎng)赶熟,這世上最難降的妖魔是什么品嚣? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上食磕,老公的妹妹穿的比我還像新娘。我一直安慰自己厅缺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著窥妇,像睡著了一般舷胜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上活翩,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天烹骨,我揣著相機(jī)與錄音,去河邊找鬼材泄。 笑死沮焕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拉宗。 我是一名探鬼主播峦树,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼旦事!你這毒婦竟也來(lái)了魁巩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤姐浮,失蹤者是張志新(化名)和其女友劉穎歪赢,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體单料,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡埋凯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扫尖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片白对。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖换怖,靈堂內(nèi)的尸體忽然破棺而出甩恼,到底是詐尸還是另有隱情,我是刑警寧澤沉颂,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布条摸,位于F島的核電站,受9級(jí)特大地震影響铸屉,放射性物質(zhì)發(fā)生泄漏钉蒲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一彻坛、第九天 我趴在偏房一處隱蔽的房頂上張望顷啼。 院中可真熱鬧踏枣,春花似錦、人聲如沸钙蒙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)躬厌。三九已至马昨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扛施,已是汗流浹背鸿捧。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留煮嫌,地道東北人笛谦。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像昌阿,于是被迫代替她去往敵國(guó)和親饥脑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容