android代理生命周期,了解 Activity 生命周期
當用戶瀏覽、退出和返回到您的應用時,您應用中的
在生命周期回調方法中,您可以聲明用戶離開和再次進入 Activity 時 Activity 的行為方式。例如,如果您正構建流媒體視頻播放器,當用戶切換至另一應用時,您可能要暫停視頻或終止網(wǎng)絡連接。當用戶返回時,您可以重新連接網(wǎng)絡并允許用戶從同一位置繼續(xù)播放視頻。換言之,每個回調都支持您執(zhí)行適合給定狀態(tài)變更的特定作業(yè)。在合適的時間執(zhí)行正確的作業(yè),并妥善處理轉換,這將提升應用的穩(wěn)健性和性能。例如,良好的生命周期回調實現(xiàn)有助于防止應用出現(xiàn)以下問題:
當用戶在使用應用時接聽來電,或切換至另一應用時崩潰。
當用戶未主動使用它時,消耗寶貴的系統(tǒng)資源。
當用戶離開應用并在稍后返回時,丟失用戶的進度。
當屏幕在橫向和縱向之間旋轉時,崩潰或丟失用戶的進度。
本文檔將詳細介紹 Activity 生命周期。首先介紹生命周期范例。接著介紹每個回調:它們執(zhí)行時內部發(fā)生了什么,以及您應該在執(zhí)行期間實現(xiàn)什么。然后,簡要介紹 Activity 狀態(tài)與導致進程被系統(tǒng)終止的漏洞之間的關系。最后,討論與在 Activity 狀態(tài)之間轉換相關的若干主題。
如需了解有關處理生命周期的信息(包括最佳做法的相關指導),請參閱使用生命周期感知型組件處理生命周期和保存界面狀態(tài)。如需了解如何將 Activity 與架構組件結合使用,以構建生產(chǎn)質量的穩(wěn)健應用,請參閱應用架構指南。
Activity 生命周期概念
為了在 Activity 生命周期的各個階段之間導航轉換,Activity 類提供六個核心回調:
圖 1 是對此范例的直觀展現(xiàn)。
圖 1. Activity 生命周期的簡化圖示。
當用戶開始離開 Activity 時,系統(tǒng)會調用方法來銷毀該 Activity。在某些情況下,此銷毀只是部分銷毀;Activity 仍然駐留在內存中(例如當用戶切換至另一應用時),并且仍然可以返回到前臺。如果用戶返回到該 Activity,Activity 會從用戶離開時的位置繼續(xù)運行。除了少數(shù)例外,應用在后臺運行時會受到限制,無法啟動 Activity。
系統(tǒng)終止給定進程及其中 Activity 的可能性取決于當時 Activity 的狀態(tài)。Activity 狀態(tài)和從內存中彈出 會更詳細地介紹狀態(tài)與彈出漏洞之間的關系。
根據(jù) Activity 的復雜程度,您可能不需要實現(xiàn)所有生命周期方法。但是,請務必了解每個方法,并實現(xiàn)能夠確保應用按用戶預期方式運行的方法,這非常重要。
在下一部分中,本文檔將詳細介紹用于處理狀態(tài)間轉換的回調。
生命周期回調
本部分介紹 Activity 生命周期中所用回調方法的相關概念及實現(xiàn)信息。
某些操作(例如調用 setContentView())屬于 Activity 生命周期方法本身。不過,用于實現(xiàn)依賴組件操作的代碼應放在組件本身內。為此,您必須使依賴組件具有生命周期感知能力。請參閱使用生命周期感知型組件處理生命周期,了解如何讓您的依賴組件獲得生命周期感知能力。
onCreate()
您必須實現(xiàn)此回調,它會在系統(tǒng)首次創(chuàng)建 Activity 時觸發(fā)。Activity 會在創(chuàng)建后進入“已創(chuàng)建”狀態(tài)。在 onCreate() 的實現(xiàn)可能會將數(shù)據(jù)綁定到列表,將 Activity 與 ViewModel 相關聯(lián),并實例化某些類作用域變量。此方法會接收 savedInstanceState 參數(shù),后者是包含 Activity 先前保存狀態(tài)的
如果您有一個生命周期感知型組件與您的 Activity 生命周期相關聯(lián),該組件將收到 ON_CREATE 事件。系統(tǒng)將調用帶有 @OnLifecycleEvent 注釋的方法,以使您的生命周期感知型組件可以執(zhí)行已創(chuàng)建狀態(tài)所需的任何設置代碼。
R.layout.main_activity 傳遞給
Kotlin
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)
}Java
TextView textView;
// some transient state for the activity instance
String gameState;
@Override
public void onCreate(Bundle savedInstanceState) {
// call the super class onCreate to complete the creation of activity like
// the view hierarchy
super.onCreate(savedInstanceState);
// recovering the instance state
if (savedInstanceState != null) {
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 = (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
public void onRestoreInstanceState(Bundle savedInstanceState) {
textView.setText(savedInstanceState.getString(TEXT_VIEW_KEY));
}
// invoked when the activity may be temporarily destroyed, save the instance state here
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(GAME_STATE_KEY, gameState);
outState.putString(TEXT_VIEW_KEY, textView.getText());
// call superclass to save any view hierarchy
super.onSaveInstanceState(outState);
}
除了定義 XML 文件,然后將其傳遞給 界面文檔。
您的 Activity 并未處于“已創(chuàng)建”狀態(tài)。下一部分將介紹
onStart()
當 Activity 進入“已開始”狀態(tài)時,系統(tǒng)會調用此回調。
當 Activity 進入已開始狀態(tài)時,與 Activity 生命周期相關聯(lián)的所有生命周期感知型組件都將收到 ON_START 事件。
onResume()
Activity 會在進入“已恢復”狀態(tài)時來到前臺,然后系統(tǒng)調用
當 Activity 進入已恢復狀態(tài)時,與 Activity 生命周期相關聯(lián)的所有生命周期感知型組件都將收到 ON_RESUME 事件。這時,生命周期組件可以啟用在組件可見且位于前臺時需要運行的任何功能,例如啟動相機預覽。
當發(fā)生中斷事件時,Activity 進入“已暫停”狀態(tài),系統(tǒng)調用
如果 Activity 從“已暫停”狀態(tài)返回“已恢復”狀態(tài),系統(tǒng)將再次調用 onPause() 期間釋放的組件,并執(zhí)行每次 Activity 進入“已恢復”狀態(tài)時必須完成的任何其他初始化操作。
以下是生命周期感知型組件的示例,該組件在收到 ON_RESUME 事件時訪問相機:
Kotlin
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun initializeCamera() {
if (camera == null) {
getCamera()
}
}
...
}Java
public class CameraComponent implements LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void initializeCamera() {
if (camera == null) {
getCamera();
}
}
...
}
LifecycleObserver 收到 ON_RESUME 事件后,上述代碼便會初始化相機。然而,在多窗口模式下,即使處于“已暫停”狀態(tài),您的 Activity 也可能完全可見。例如,當用戶處于多窗口模式,并點按另一個不包含 Activity 的窗口時,您的 Activity 將進入“已暫停”狀態(tài)。如果您希望相機僅在應用處于“已恢復”(可見且在前臺運行)狀態(tài)時可用,請在收到上述 ON_RESUME 事件后初始化相機。如果您希望在 Activity 處于“已暫停”狀態(tài)但可見時(例如在多窗口模式下)保持相機可用,應在收到 ON_START 事件后初始化相機。但請注意,若要讓相機在 Activity 處于“已暫停”狀態(tài)時可用,可能會導致系統(tǒng)在多窗口模式下拒絕其他處于“已恢復”狀態(tài)的應用訪問相機。有時可能有必要讓相機在 Activity 處于“已暫停”狀態(tài)時保持可用,但這樣做實際可能會降低整體用戶體驗。請仔細考慮,生命周期的哪個階段更適合在多窗口環(huán)境下控制共享系統(tǒng)資源。如需詳細了解如何支持多窗口模式,請參閱多窗口支持。
無論您選擇在哪個構建事件中執(zhí)行初始化操作,都請務必使用相應的生命周期事件來釋放資源。如果您在收到 ON_START 事件后初始化某些內容,請在收到 ON_STOP 事件后釋放或終止相應內容。如果您在收到 ON_RESUME 事件后初始化某些內容,請在收到 ON_PAUSE 事件后將其釋放。
請注意,上述代碼段將相機初始化代碼放置在生命周期感知型組件中。您也可以直接將此代碼放入 Activity 生命周期回調(例如 onStart() 和 onStop()),但我們不建議您這樣做。通過將此邏輯添加到獨立的生命周期感知型組件中,您可以對多個 Activity 重復使用該組件,而無需復制代碼。請參閱使用生命周期感知型組件處理生命周期,了解如何創(chuàng)建生命周期感知型組件。
onPause()
系統(tǒng)將此方法視為用戶將要離開您的 Activity 的第一個標志(盡管這并不總是意味著 Activity 會被銷毀);此方法表示 Activity 不再位于前臺(盡管在用戶處于多窗口模式時 Activity 仍然可見)。使用 onPause() 方法暫停或調整當 Activity 處于“已暫停”狀態(tài)時不應繼續(xù)(或應有節(jié)制地繼續(xù))的操作,以及您希望很快恢復的操作。Activity 進入此狀態(tài)的原因有很多。例如:
如 onResume() 部分所述,某個事件會中斷應用執(zhí)行。這是最常見的情況。
在 Android 7.0(API 級別 24)或更高版本中,有多個應用在多窗口模式下運行。無論何時,都只有一個應用(窗口)可以擁有焦點,因此系統(tǒng)會暫停所有其他應用。
有新的半透明 Activity(例如對話框)處于開啟狀態(tài)。只要 Activity 仍然部分可見但并未處于焦點之中,它便會一直暫停。
當 Activity 進入已暫停狀態(tài)時,與 Activity 生命周期相關聯(lián)的所有生命周期感知型組件都將收到 ON_PAUSE 事件。這時,生命周期組件可以停止在組件未位于前臺時無需運行的任何功能,例如停止相機預覽。
您還可以使用 onPause() 方法釋放系統(tǒng)資源、傳感器(例如 GPS)手柄,或當您的 Activity 暫停且用戶不需要它們時仍然可能影響電池續(xù)航時間的任何資源。然而,正如上文的 onResume() 部分所述,如果處于多窗口模式,“已暫停”的 Activity 仍完全可見。因此,您應該考慮使用 onStop() 而非 onPause() 來完全釋放或調整與界面相關的資源和操作,以便更好地支持多窗口模式。
響應 ON_PAUSE 事件的以下 LifecycleObserver 示例與上述 ON_RESUME 事件示例相對應,會釋放在收到 ON_RESUME 事件后初始化的相機:
Kotlin
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun releaseCamera() {
camera?.release()
camera = null
}
...
}Java
public class JavaCameraComponent implements LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void releaseCamera() {
if (camera != null) {
camera.release();
camera = null;
}
}
...
}
請注意,上述代碼段在 LifecycleObserver 收到 ON_PAUSE 事件后放置相機釋放代碼。如前所述,請參閱使用生命周期感知型組件處理生命周期了解如何創(chuàng)建生命周期感知型組件。
不應使用 onStop()。如需詳細了解如何保存數(shù)據(jù),請參閱保存和恢復 Activity 狀態(tài)。
onStop()
如果您的 Activity 不再對用戶可見,說明其已進入“已停止”狀態(tài),因此系統(tǒng)將調用 例如,當新啟動的 Activity 覆蓋整個屏幕時,可能會發(fā)生這種情況。如果 Activity 已結束運行并即將終止,系統(tǒng)還可以調用
當 Activity 進入已停止狀態(tài)時,與 Activity 生命周期相關聯(lián)的所有生命周期感知型組件都將收到 ON_STOP 事件。這時,生命周期組件可以停止在組件未顯示在屏幕上時無需運行的任何功能。
在
您還應使用
Kotlin
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.
)
}Java
@Override
protected void 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.
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
// do this update in background on an AsyncQueryHandler or equivalent
asyncQueryHandler.startUpdate (
mToken, // 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.
);
}
請注意,上述代碼示例直接使用 SQLite。但您應該改用 Room,這是一個通過 SQLite 提供抽象層的持久性庫。如需詳細了解使用 Room 的好處,以及如何在應用中實現(xiàn) Room,請參閱 Room 持久性庫指南。
當您的 Activity 進入“已停止”狀態(tài)時,
注意:Activity 停止后,如果系統(tǒng)需要恢復內存,可能會銷毀包含該 Activity 的進程。即使系統(tǒng)在 Activity 停止后銷毀相應進程,系統(tǒng)仍會保留 保存和恢復 Activity 狀態(tài)。
進入“已停止”狀態(tài)后,Activity 要么返回與用戶互動,要么結束運行并消失。如果 Activity 返回,系統(tǒng)將調用
onDestroy()
銷毀 Ativity 之前,系統(tǒng)會先調用 onDestroy()。系統(tǒng)調用此回調的原因如下:Activity 即將結束(由于用戶徹底關閉 Activity 或由于系統(tǒng)為 Activity 調用 finish()),或者
由于配置變更(例如設備旋轉或多窗口模式),系統(tǒng)暫時銷毀 Activity
當 Activity 進入已銷毀狀態(tài)時,與 Activity 生命周期相關聯(lián)的所有生命周期感知型組件都將收到 ON_DESTROY 事件。這時,生命周期組件可以在 Activity 被銷毀之前清理所需的任何數(shù)據(jù)。
您應使用 ViewModel 對象來包含 Activity 的相關視圖數(shù)據(jù),而不是在您的 Activity 中加入邏輯來確定 Activity 被銷毀的原因。如果因配置變更而重新創(chuàng)建 Activity,ViewModel 不必執(zhí)行任何操作,因為系統(tǒng)將保留 ViewModel 并將其提供給下一個 Activity 實例。如果不重新創(chuàng)建 Activity,ViewModel 將調用 onCleared() 方法,以便在 Activity 被銷毀前清除所需的任何數(shù)據(jù)。
您可以使用 isFinishing() 方法區(qū)分這兩種情況。
如果 Activity 即將結束,onDestroy() 是 Activity 收到的最后一個生命周期回調。如果由于配置變更而調用 onDestroy(),系統(tǒng)會立即新建 Activity 實例,然后在新配置中為新實例調用 onCreate()。
onDestroy() 回調應釋放先前的回調(例如 onStop())尚未釋放的所有資源。
Activity 狀態(tài)和從內存中彈出
系統(tǒng)會在需要釋放 RAM 時終止進程;系統(tǒng)終止給定進程的可能性取決于當時進程的狀態(tài)。反之,進程狀態(tài)取決于在進程中運行的 Activity 的狀態(tài)。表 1 展示了進程狀態(tài)、Activity 狀態(tài)以及系統(tǒng)終止進程的可能性之間的關系。
系統(tǒng)終止進程的可能性
進程狀態(tài)
Activity 狀態(tài)
較小
前臺(擁有或即將獲得焦點)
已創(chuàng)建
已開始
已恢復
較大
后臺(失去焦點)
已暫停
最大
后臺(不可見)
已停止
空
已銷毀
表 1. 進程生命周期和 Activity 狀態(tài)之間的關系
系統(tǒng)永遠不會直接終止 Activity 以釋放內存,而是會終止 Activity 所在的進程。系統(tǒng)不僅會銷毀 Activity,還會銷毀在該進程中運行的所有其他內容。如需了解如何在系統(tǒng)啟動的進程被終止時保留和恢復 Activity 的界面狀態(tài),請參閱保存和恢復 Activity 狀態(tài)。
用戶還可以使用“設置”下的“應用管理器”來終止進程,以終止相應的應用。
如需詳細了解一般進程,請參閱進程和線程。如需詳細了解進程生命周期如何與其中 Activity 的狀態(tài)相關聯(lián),請參閱相應頁面的進程生命周期部分。
保存和恢復瞬時界面狀態(tài)
用戶期望 Activity 的界面狀態(tài)在整個配置變更(例如旋轉或切換到多窗口模式)期間保持不變。但是,默認情況下,系統(tǒng)會在發(fā)生此類配置更改時銷毀 Activity,從而清除存儲在 Activity 實例中的任何界面狀態(tài)。同樣,如果用戶暫時從您的應用切換到其他應用,并在稍后返回您的應用,他們也希望界面狀態(tài)保持不變。但是,當用戶離開應用且您的 Activity 停止時,系統(tǒng)可能會銷毀該應用的進程。
當 Activity 因系統(tǒng)限制而被銷毀時,您應組合使用 ViewModel、onSaveInstanceState() 和/或本地存儲來保留用戶的瞬時界面狀態(tài)。如需詳細了解用戶期望與系統(tǒng)行為,以及如何在系統(tǒng)啟動的 Activity 和進程被終止后最大程度地保留復雜的界面狀態(tài)數(shù)據(jù),請參閱保存界面狀態(tài)。
本部分概述了實例狀態(tài)的定義,以及如何實現(xiàn) onSaveInstance() 方法,該方法是對 Activity 本身的回調。如果界面數(shù)據(jù)簡單且輕量,例如原始數(shù)據(jù)類型或簡單對象(比如 String),您可以單獨使用 onSaveInstanceState() 使界面狀態(tài)在配置更改和系統(tǒng)啟動的進程被終止時保持不變。但在大多數(shù)情況下,您應使用 ViewModel 和 onSaveInstanceState()(如保存界面狀態(tài)中所述),因為 onSaveInstanceState() 會產(chǎn)生序列化/反序列化費用。
實例狀態(tài)
在某些情況下,您的 Activity 會因正常的應用行為而被銷毀,例如當用戶按下返回按鈕或您的 Activity 通過調用 finish() 方法發(fā)出銷毀信號時。當您的 Activity 因用戶按下返回按鈕或因其自行結束而被銷毀時,系統(tǒng)和用戶對該 Activity 實例的概念將永遠消失。在這些情況下,用戶的期望與系統(tǒng)行為相匹配,您無需完成任何額外工作。
但是,如果系統(tǒng)因系統(tǒng)限制(例如配置變更或內存壓力)而銷毀 Activity,雖然實際的 Activity 實例會消失,但系統(tǒng)會記住它曾經(jīng)存在過。如果用戶嘗試回退到該 Activity,系統(tǒng)將使用一組描述 Activity 銷毀時狀態(tài)的已保存數(shù)據(jù)新建該 Activity 的實例。
系統(tǒng)用于恢復先前狀態(tài)的已保存數(shù)據(jù)稱為實例狀態(tài),是存儲在 Bundle 對象中的鍵值對集合。默認情況下,系統(tǒng)使用 Bundle 實例狀態(tài)來保存 Activity 布局中每個 View 對象的相關信息(例如在 EditText 微件中輸入的文本值)。這樣,如果您的 Activity 實例被銷毀并重新創(chuàng)建,布局狀態(tài)便會恢復為其先前的狀態(tài),且您無需編寫代碼。但是,您的 Activity 可能包含您要恢復的更多狀態(tài)信息,例如追蹤用戶在 Activity 中的進程的成員變量。
注意:為了使 Android 系統(tǒng)恢復 Activity 中視圖的狀態(tài),每個視圖必須具有 android:id 屬性提供的唯一 ID。
Bundle 對象并不適合保留大量數(shù)據(jù),因為它需要在主線程上進行序列化處理并占用系統(tǒng)進程內存。如需保存大量數(shù)據(jù),您應組合使用持久性本地存儲、onSaveInstanceState() 方法和 ViewModel 類來保存數(shù)據(jù),正如保存界面狀態(tài)中所述。
使用 onSaveInstanceState() 保存簡單輕量的界面狀態(tài)
當您的 Activity 開始停止時,系統(tǒng)會調用 onSaveInstanceState() 方法,以便您的 Activity 可以將狀態(tài)信息保存到實例狀態(tài) Bundle 中。此方法的默認實現(xiàn)保存有關 Activity 視圖層次結構狀態(tài)的瞬時信息,例如 EditText 微件中的文本或 ListView 微件的滾動位置。
如需保存 Activity 的其他實例狀態(tài)信息,您必須替換 onSaveInstanceState(),并將鍵值對添加到您的 Activity 意外銷毀時事件中所保存的 Bundle 對象中。替換 onSaveInstanceState() 時,如果您希望默認實現(xiàn)保存視圖層次結構的狀態(tài),必須調用父類實現(xiàn)。例如:
Kotlin
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"
}Java
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
// ...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, currentScore);
savedInstanceState.putInt(STATE_LEVEL, currentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
注意:當用戶顯式關閉 Activity 時,或者在其他情況下調用 finish() 時,系統(tǒng)不會調用 onSaveInstanceState()。
如需保存持久性數(shù)據(jù)(例如用戶首選項或數(shù)據(jù)庫中的數(shù)據(jù)),您應在 Activity 位于前臺時抓住合適機會。如果沒有這樣的時機,您應在執(zhí)行 onStop() 方法期間保存此類數(shù)據(jù)。
使用保存的實例狀態(tài)恢復 Activity 界面狀態(tài)
重建先前被銷毀的 Activity 后,您可以從系統(tǒng)傳遞給 Activity 的 Bundle 中恢復保存的實例狀態(tài)。onCreate() 和 onRestoreInstanceState() 回調方法均會收到包含實例狀態(tài)信息的相同 Bundle。
因為無論系統(tǒng)是新建 Activity 實例還是重新創(chuàng)建之前的實例,都會調用 onCreate() 方法,所以在嘗試讀取之前,您必須檢查狀態(tài) Bundle 是否為 null。如果為 null,系統(tǒng)將新建 Activity 實例,而不會恢復之前銷毀的實例。
例如,以下代碼段顯示如何在 onCreate() 中恢復某些狀態(tài)數(shù)據(jù):
Kotlin
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
}
// ...
}Java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
currentScore = savedInstanceState.getInt(STATE_SCORE);
currentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
// ...
}
Kotlin
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)
}
}Java
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
currentScore = savedInstanceState.getInt(STATE_SCORE);
currentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
注意:您應始終調用 onRestoreInstanceState() 的父類實現(xiàn),以便默認實現(xiàn)可以恢復視圖層次結構的狀態(tài)。
在 Activity 之間導航
在應用的生命周期中,應用很可能會多次進入和退出 Activity。例如,用戶可以點按設備的返回按鈕,或者 Activity 可能需要啟動不同的 Activity。本部分介紹了實現(xiàn)成功的 Activity 轉換需要了解的主題。這些主題包括從另一個 Activity 啟動 Activity、保存 Activity 狀態(tài),以及恢復 Activity 狀態(tài)。
從一個 Activity 啟動另一個 Activity
Activity 通常需要在某個時刻啟動另一個 Activity。例如,當應用需要從當前屏幕移動到新屏幕時,就會出現(xiàn)這種需求。
根據(jù)您的 Activity 是否希望從即將啟動的新 Activity 中獲取返回結果,您可以使用
Intent 和 Intent 過濾器。
startActivity()
如果新啟動的 Activity 不需要返回結果,當前 Activity 可以通過調用
在自己的應用中工作時,您通常只需啟動已知 Activity。例如,以下代碼段顯示如何啟動一個名為 SignInActivity 的 Activity。
Kotlin
val intent = Intent(this, SignInActivity::class.java)
startActivity(intent)Java
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
您的應用可能還希望使用 Activity 中的數(shù)據(jù)執(zhí)行某些操作,例如發(fā)送電子郵件、短信或狀態(tài)更新。在這種情況下,您的應用自身可能不具有執(zhí)行此類操作所需的 Activity,因此您可以改為利用設備上其他應用提供的 Activity 為您執(zhí)行這些操作。這便是 intent 的真正價值所在。您可以創(chuàng)建一個 intent,對您想執(zhí)行的操作進行描述,系統(tǒng)會從其他應用啟動相應的 Activity。如果有多個 Activity 可以處理 intent,用戶可以選擇要使用哪一個。例如,如果您想允許用戶發(fā)送電子郵件,可以創(chuàng)建以下 intent:
Kotlin
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_EMAIL, recipientArray)
}
startActivity(intent)Java
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
添加到 intent 中的 EXTRA_EMAIL extra 是一個字符串數(shù)組,其中包含電子郵件的收件人電子郵件地址。當電子郵件應用響應此 intent 時,該應用會讀取 extra 中提供的字符串數(shù)組,并將該數(shù)組放入電子郵件撰寫表單的“收件人”字段。在這種情況下,電子郵件應用的 Activity 會啟動,并且當用戶完成操作時,您的 Activity 會繼續(xù)運行。
startActivityForResult()
有時,您會希望在 Activity 結束時從 Activity 中獲取返回結果。例如,您可以啟動一項 Activity,讓用戶在聯(lián)系人列表中選擇收件人;當 Activity 結束時,系統(tǒng)將返回用戶選擇的收件人。為此,您可以調用
當子級 Activity 退出時,它可以調用 setResult(int) 將數(shù)據(jù)返回到其父級。子級 Activity 必須始終提供結果代碼,該結果代碼可以是標準結果 RESULT_CANCELED、RESULT_OK,也可以是從 RESULT_FIRST_USER 開始的任何自定義值。此外,子級 Activity 可以根據(jù)需要返回包含它所需的任何其他數(shù)據(jù)的
如果子級 Activity 由于任何原因(例如崩潰)而失敗,父級 Activity 將收到代碼為 RESULT_CANCELED 的結果。
Kotlin
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
}
}Java
public class MyActivity extends Activity {
// ...
static final int PICK_CONTACT_REQUEST = 0;
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
// When the user center presses, let them pick a contact.
startActivityForResult(
new Intent(Intent.ACTION_PICK,
new Uri("content://contacts")),
PICK_CONTACT_REQUEST);
return true;
}
return false;
}
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == PICK_CONTACT_REQUEST) {
if (resultCode == RESULT_OK) {
// A contact was picked. Here we will just display it
// to the user.
startActivity(new Intent(Intent.ACTION_VIEW, data));
}
}
}
}
協(xié)調 Activity
當一個 Activity 啟動另一個 Activity 時,它們都會經(jīng)歷生命周期轉換。第一個 Activity 停止運行并進入“已暫停”或“已停止”狀態(tài),同時創(chuàng)建另一個 Activity。如果這些 Activity 共享保存到磁盤或其他位置的數(shù)據(jù),必須要明確第一個 Activity 在創(chuàng)建第二個 Activity 之前并未完全停止。相反,啟動第二個 Activity 的過程與停止第一個 Activity 的過程重疊。
生命周期回調的順序已有明確定義,特別是當兩個 Activity 在同一個進程(應用)中,并且其中一個要啟動另一個時。以下是 Activity A 啟動 Activity B 時的操作發(fā)生順序:
Activity A 的
Activity B 的
然后,如果 Activity A 在屏幕上不再顯示,其
您可以利用這種可預測的生命周期回調順序管理從一個 Activity 到另一個 Activity 的信息轉換。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的android代理生命周期,了解 Activity 生命周期的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode 861. 翻转矩阵后的
- 下一篇: 二级vb笔试题库__全国计算机等级考试,