當(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)。
圖 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 布局文件。
<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ī):
<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ī):
<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ǔ)空間中:
<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)。例如:
<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ù):
<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:
<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溪窒。
<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:
<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é)果逞力。
<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)換火架。