android代理生命周期,了解 Activity 生命周期
當用戶瀏覽、退出和返回到您的應用時,您應用中的
在生命周期回調方法中,您可以聲明用戶離開和再次進入 Activity 時 Activity 的行為方式。例如,如果您正構建流媒體視頻播放器,當用戶切換至另一應用時,您可能要暫停視頻或終止網絡連接。當用戶返回時,您可以重新連接網絡并允許用戶從同一位置繼續播放視頻。換言之,每個回調都支持您執行適合給定狀態變更的特定作業。在合適的時間執行正確的作業,并妥善處理轉換,這將提升應用的穩健性和性能。例如,良好的生命周期回調實現有助于防止應用出現以下問題:
當用戶在使用應用時接聽來電,或切換至另一應用時崩潰。
當用戶未主動使用它時,消耗寶貴的系統資源。
當用戶離開應用并在稍后返回時,丟失用戶的進度。
當屏幕在橫向和縱向之間旋轉時,崩潰或丟失用戶的進度。
本文檔將詳細介紹 Activity 生命周期。首先介紹生命周期范例。接著介紹每個回調:它們執行時內部發生了什么,以及您應該在執行期間實現什么。然后,簡要介紹 Activity 狀態與導致進程被系統終止的漏洞之間的關系。最后,討論與在 Activity 狀態之間轉換相關的若干主題。
如需了解有關處理生命周期的信息(包括最佳做法的相關指導),請參閱使用生命周期感知型組件處理生命周期和保存界面狀態。如需了解如何將 Activity 與架構組件結合使用,以構建生產質量的穩健應用,請參閱應用架構指南。
Activity 生命周期概念
為了在 Activity 生命周期的各個階段之間導航轉換,Activity 類提供六個核心回調:
圖 1 是對此范例的直觀展現。
圖 1. Activity 生命周期的簡化圖示。
當用戶開始離開 Activity 時,系統會調用方法來銷毀該 Activity。在某些情況下,此銷毀只是部分銷毀;Activity 仍然駐留在內存中(例如當用戶切換至另一應用時),并且仍然可以返回到前臺。如果用戶返回到該 Activity,Activity 會從用戶離開時的位置繼續運行。除了少數例外,應用在后臺運行時會受到限制,無法啟動 Activity。
系統終止給定進程及其中 Activity 的可能性取決于當時 Activity 的狀態。Activity 狀態和從內存中彈出 會更詳細地介紹狀態與彈出漏洞之間的關系。
根據 Activity 的復雜程度,您可能不需要實現所有生命周期方法。但是,請務必了解每個方法,并實現能夠確保應用按用戶預期方式運行的方法,這非常重要。
在下一部分中,本文檔將詳細介紹用于處理狀態間轉換的回調。
生命周期回調
本部分介紹 Activity 生命周期中所用回調方法的相關概念及實現信息。
某些操作(例如調用 setContentView())屬于 Activity 生命周期方法本身。不過,用于實現依賴組件操作的代碼應放在組件本身內。為此,您必須使依賴組件具有生命周期感知能力。請參閱使用生命周期感知型組件處理生命周期,了解如何讓您的依賴組件獲得生命周期感知能力。
onCreate()
您必須實現此回調,它會在系統首次創建 Activity 時觸發。Activity 會在創建后進入“已創建”狀態。在 onCreate() 的實現可能會將數據綁定到列表,將 Activity 與 ViewModel 相關聯,并實例化某些類作用域變量。此方法會接收 savedInstanceState 參數,后者是包含 Activity 先前保存狀態的
如果您有一個生命周期感知型組件與您的 Activity 生命周期相關聯,該組件將收到 ON_CREATE 事件。系統將調用帶有 @OnLifecycleEvent 注釋的方法,以使您的生命周期感知型組件可以執行已創建狀態所需的任何設置代碼。
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 并未處于“已創建”狀態。下一部分將介紹
onStart()
當 Activity 進入“已開始”狀態時,系統會調用此回調。
當 Activity 進入已開始狀態時,與 Activity 生命周期相關聯的所有生命周期感知型組件都將收到 ON_START 事件。
onResume()
Activity 會在進入“已恢復”狀態時來到前臺,然后系統調用
當 Activity 進入已恢復狀態時,與 Activity 生命周期相關聯的所有生命周期感知型組件都將收到 ON_RESUME 事件。這時,生命周期組件可以啟用在組件可見且位于前臺時需要運行的任何功能,例如啟動相機預覽。
當發生中斷事件時,Activity 進入“已暫停”狀態,系統調用
如果 Activity 從“已暫停”狀態返回“已恢復”狀態,系統將再次調用 onPause() 期間釋放的組件,并執行每次 Activity 進入“已恢復”狀態時必須完成的任何其他初始化操作。
以下是生命周期感知型組件的示例,該組件在收到 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 事件后,上述代碼便會初始化相機。然而,在多窗口模式下,即使處于“已暫停”狀態,您的 Activity 也可能完全可見。例如,當用戶處于多窗口模式,并點按另一個不包含 Activity 的窗口時,您的 Activity 將進入“已暫停”狀態。如果您希望相機僅在應用處于“已恢復”(可見且在前臺運行)狀態時可用,請在收到上述 ON_RESUME 事件后初始化相機。如果您希望在 Activity 處于“已暫停”狀態但可見時(例如在多窗口模式下)保持相機可用,應在收到 ON_START 事件后初始化相機。但請注意,若要讓相機在 Activity 處于“已暫停”狀態時可用,可能會導致系統在多窗口模式下拒絕其他處于“已恢復”狀態的應用訪問相機。有時可能有必要讓相機在 Activity 處于“已暫停”狀態時保持可用,但這樣做實際可能會降低整體用戶體驗。請仔細考慮,生命周期的哪個階段更適合在多窗口環境下控制共享系統資源。如需詳細了解如何支持多窗口模式,請參閱多窗口支持。
無論您選擇在哪個構建事件中執行初始化操作,都請務必使用相應的生命周期事件來釋放資源。如果您在收到 ON_START 事件后初始化某些內容,請在收到 ON_STOP 事件后釋放或終止相應內容。如果您在收到 ON_RESUME 事件后初始化某些內容,請在收到 ON_PAUSE 事件后將其釋放。
請注意,上述代碼段將相機初始化代碼放置在生命周期感知型組件中。您也可以直接將此代碼放入 Activity 生命周期回調(例如 onStart() 和 onStop()),但我們不建議您這樣做。通過將此邏輯添加到獨立的生命周期感知型組件中,您可以對多個 Activity 重復使用該組件,而無需復制代碼。請參閱使用生命周期感知型組件處理生命周期,了解如何創建生命周期感知型組件。
onPause()
系統將此方法視為用戶將要離開您的 Activity 的第一個標志(盡管這并不總是意味著 Activity 會被銷毀);此方法表示 Activity 不再位于前臺(盡管在用戶處于多窗口模式時 Activity 仍然可見)。使用 onPause() 方法暫停或調整當 Activity 處于“已暫停”狀態時不應繼續(或應有節制地繼續)的操作,以及您希望很快恢復的操作。Activity 進入此狀態的原因有很多。例如:
如 onResume() 部分所述,某個事件會中斷應用執行。這是最常見的情況。
在 Android 7.0(API 級別 24)或更高版本中,有多個應用在多窗口模式下運行。無論何時,都只有一個應用(窗口)可以擁有焦點,因此系統會暫停所有其他應用。
有新的半透明 Activity(例如對話框)處于開啟狀態。只要 Activity 仍然部分可見但并未處于焦點之中,它便會一直暫停。
當 Activity 進入已暫停狀態時,與 Activity 生命周期相關聯的所有生命周期感知型組件都將收到 ON_PAUSE 事件。這時,生命周期組件可以停止在組件未位于前臺時無需運行的任何功能,例如停止相機預覽。
您還可以使用 onPause() 方法釋放系統資源、傳感器(例如 GPS)手柄,或當您的 Activity 暫停且用戶不需要它們時仍然可能影響電池續航時間的任何資源。然而,正如上文的 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 事件后放置相機釋放代碼。如前所述,請參閱使用生命周期感知型組件處理生命周期了解如何創建生命周期感知型組件。
不應使用 onStop()。如需詳細了解如何保存數據,請參閱保存和恢復 Activity 狀態。
onStop()
如果您的 Activity 不再對用戶可見,說明其已進入“已停止”狀態,因此系統將調用 例如,當新啟動的 Activity 覆蓋整個屏幕時,可能會發生這種情況。如果 Activity 已結束運行并即將終止,系統還可以調用
當 Activity 進入已停止狀態時,與 Activity 生命周期相關聯的所有生命周期感知型組件都將收到 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 的好處,以及如何在應用中實現 Room,請參閱 Room 持久性庫指南。
當您的 Activity 進入“已停止”狀態時,
注意:Activity 停止后,如果系統需要恢復內存,可能會銷毀包含該 Activity 的進程。即使系統在 Activity 停止后銷毀相應進程,系統仍會保留 保存和恢復 Activity 狀態。
進入“已停止”狀態后,Activity 要么返回與用戶互動,要么結束運行并消失。如果 Activity 返回,系統將調用
onDestroy()
銷毀 Ativity 之前,系統會先調用 onDestroy()。系統調用此回調的原因如下:Activity 即將結束(由于用戶徹底關閉 Activity 或由于系統為 Activity 調用 finish()),或者
由于配置變更(例如設備旋轉或多窗口模式),系統暫時銷毀 Activity
當 Activity 進入已銷毀狀態時,與 Activity 生命周期相關聯的所有生命周期感知型組件都將收到 ON_DESTROY 事件。這時,生命周期組件可以在 Activity 被銷毀之前清理所需的任何數據。
您應使用 ViewModel 對象來包含 Activity 的相關視圖數據,而不是在您的 Activity 中加入邏輯來確定 Activity 被銷毀的原因。如果因配置變更而重新創建 Activity,ViewModel 不必執行任何操作,因為系統將保留 ViewModel 并將其提供給下一個 Activity 實例。如果不重新創建 Activity,ViewModel 將調用 onCleared() 方法,以便在 Activity 被銷毀前清除所需的任何數據。
您可以使用 isFinishing() 方法區分這兩種情況。
如果 Activity 即將結束,onDestroy() 是 Activity 收到的最后一個生命周期回調。如果由于配置變更而調用 onDestroy(),系統會立即新建 Activity 實例,然后在新配置中為新實例調用 onCreate()。
onDestroy() 回調應釋放先前的回調(例如 onStop())尚未釋放的所有資源。
Activity 狀態和從內存中彈出
系統會在需要釋放 RAM 時終止進程;系統終止給定進程的可能性取決于當時進程的狀態。反之,進程狀態取決于在進程中運行的 Activity 的狀態。表 1 展示了進程狀態、Activity 狀態以及系統終止進程的可能性之間的關系。
系統終止進程的可能性
進程狀態
Activity 狀態
較小
前臺(擁有或即將獲得焦點)
已創建
已開始
已恢復
較大
后臺(失去焦點)
已暫停
最大
后臺(不可見)
已停止
空
已銷毀
表 1. 進程生命周期和 Activity 狀態之間的關系
系統永遠不會直接終止 Activity 以釋放內存,而是會終止 Activity 所在的進程。系統不僅會銷毀 Activity,還會銷毀在該進程中運行的所有其他內容。如需了解如何在系統啟動的進程被終止時保留和恢復 Activity 的界面狀態,請參閱保存和恢復 Activity 狀態。
用戶還可以使用“設置”下的“應用管理器”來終止進程,以終止相應的應用。
如需詳細了解一般進程,請參閱進程和線程。如需詳細了解進程生命周期如何與其中 Activity 的狀態相關聯,請參閱相應頁面的進程生命周期部分。
保存和恢復瞬時界面狀態
用戶期望 Activity 的界面狀態在整個配置變更(例如旋轉或切換到多窗口模式)期間保持不變。但是,默認情況下,系統會在發生此類配置更改時銷毀 Activity,從而清除存儲在 Activity 實例中的任何界面狀態。同樣,如果用戶暫時從您的應用切換到其他應用,并在稍后返回您的應用,他們也希望界面狀態保持不變。但是,當用戶離開應用且您的 Activity 停止時,系統可能會銷毀該應用的進程。
當 Activity 因系統限制而被銷毀時,您應組合使用 ViewModel、onSaveInstanceState() 和/或本地存儲來保留用戶的瞬時界面狀態。如需詳細了解用戶期望與系統行為,以及如何在系統啟動的 Activity 和進程被終止后最大程度地保留復雜的界面狀態數據,請參閱保存界面狀態。
本部分概述了實例狀態的定義,以及如何實現 onSaveInstance() 方法,該方法是對 Activity 本身的回調。如果界面數據簡單且輕量,例如原始數據類型或簡單對象(比如 String),您可以單獨使用 onSaveInstanceState() 使界面狀態在配置更改和系統啟動的進程被終止時保持不變。但在大多數情況下,您應使用 ViewModel 和 onSaveInstanceState()(如保存界面狀態中所述),因為 onSaveInstanceState() 會產生序列化/反序列化費用。
實例狀態
在某些情況下,您的 Activity 會因正常的應用行為而被銷毀,例如當用戶按下返回按鈕或您的 Activity 通過調用 finish() 方法發出銷毀信號時。當您的 Activity 因用戶按下返回按鈕或因其自行結束而被銷毀時,系統和用戶對該 Activity 實例的概念將永遠消失。在這些情況下,用戶的期望與系統行為相匹配,您無需完成任何額外工作。
但是,如果系統因系統限制(例如配置變更或內存壓力)而銷毀 Activity,雖然實際的 Activity 實例會消失,但系統會記住它曾經存在過。如果用戶嘗試回退到該 Activity,系統將使用一組描述 Activity 銷毀時狀態的已保存數據新建該 Activity 的實例。
系統用于恢復先前狀態的已保存數據稱為實例狀態,是存儲在 Bundle 對象中的鍵值對集合。默認情況下,系統使用 Bundle 實例狀態來保存 Activity 布局中每個 View 對象的相關信息(例如在 EditText 微件中輸入的文本值)。這樣,如果您的 Activity 實例被銷毀并重新創建,布局狀態便會恢復為其先前的狀態,且您無需編寫代碼。但是,您的 Activity 可能包含您要恢復的更多狀態信息,例如追蹤用戶在 Activity 中的進程的成員變量。
注意:為了使 Android 系統恢復 Activity 中視圖的狀態,每個視圖必須具有 android:id 屬性提供的唯一 ID。
Bundle 對象并不適合保留大量數據,因為它需要在主線程上進行序列化處理并占用系統進程內存。如需保存大量數據,您應組合使用持久性本地存儲、onSaveInstanceState() 方法和 ViewModel 類來保存數據,正如保存界面狀態中所述。
使用 onSaveInstanceState() 保存簡單輕量的界面狀態
當您的 Activity 開始停止時,系統會調用 onSaveInstanceState() 方法,以便您的 Activity 可以將狀態信息保存到實例狀態 Bundle 中。此方法的默認實現保存有關 Activity 視圖層次結構狀態的瞬時信息,例如 EditText 微件中的文本或 ListView 微件的滾動位置。
如需保存 Activity 的其他實例狀態信息,您必須替換 onSaveInstanceState(),并將鍵值對添加到您的 Activity 意外銷毀時事件中所保存的 Bundle 對象中。替換 onSaveInstanceState() 時,如果您希望默認實現保存視圖層次結構的狀態,必須調用父類實現。例如:
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() 時,系統不會調用 onSaveInstanceState()。
如需保存持久性數據(例如用戶首選項或數據庫中的數據),您應在 Activity 位于前臺時抓住合適機會。如果沒有這樣的時機,您應在執行 onStop() 方法期間保存此類數據。
使用保存的實例狀態恢復 Activity 界面狀態
重建先前被銷毀的 Activity 后,您可以從系統傳遞給 Activity 的 Bundle 中恢復保存的實例狀態。onCreate() 和 onRestoreInstanceState() 回調方法均會收到包含實例狀態信息的相同 Bundle。
因為無論系統是新建 Activity 實例還是重新創建之前的實例,都會調用 onCreate() 方法,所以在嘗試讀取之前,您必須檢查狀態 Bundle 是否為 null。如果為 null,系統將新建 Activity 實例,而不會恢復之前銷毀的實例。
例如,以下代碼段顯示如何在 onCreate() 中恢復某些狀態數據:
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() 的父類實現,以便默認實現可以恢復視圖層次結構的狀態。
在 Activity 之間導航
在應用的生命周期中,應用很可能會多次進入和退出 Activity。例如,用戶可以點按設備的返回按鈕,或者 Activity 可能需要啟動不同的 Activity。本部分介紹了實現成功的 Activity 轉換需要了解的主題。這些主題包括從另一個 Activity 啟動 Activity、保存 Activity 狀態,以及恢復 Activity 狀態。
從一個 Activity 啟動另一個 Activity
Activity 通常需要在某個時刻啟動另一個 Activity。例如,當應用需要從當前屏幕移動到新屏幕時,就會出現這種需求。
根據您的 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 中的數據執行某些操作,例如發送電子郵件、短信或狀態更新。在這種情況下,您的應用自身可能不具有執行此類操作所需的 Activity,因此您可以改為利用設備上其他應用提供的 Activity 為您執行這些操作。這便是 intent 的真正價值所在。您可以創建一個 intent,對您想執行的操作進行描述,系統會從其他應用啟動相應的 Activity。如果有多個 Activity 可以處理 intent,用戶可以選擇要使用哪一個。例如,如果您想允許用戶發送電子郵件,可以創建以下 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 是一個字符串數組,其中包含電子郵件的收件人電子郵件地址。當電子郵件應用響應此 intent 時,該應用會讀取 extra 中提供的字符串數組,并將該數組放入電子郵件撰寫表單的“收件人”字段。在這種情況下,電子郵件應用的 Activity 會啟動,并且當用戶完成操作時,您的 Activity 會繼續運行。
startActivityForResult()
有時,您會希望在 Activity 結束時從 Activity 中獲取返回結果。例如,您可以啟動一項 Activity,讓用戶在聯系人列表中選擇收件人;當 Activity 結束時,系統將返回用戶選擇的收件人。為此,您可以調用
當子級 Activity 退出時,它可以調用 setResult(int) 將數據返回到其父級。子級 Activity 必須始終提供結果代碼,該結果代碼可以是標準結果 RESULT_CANCELED、RESULT_OK,也可以是從 RESULT_FIRST_USER 開始的任何自定義值。此外,子級 Activity 可以根據需要返回包含它所需的任何其他數據的
如果子級 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));
}
}
}
}
協調 Activity
當一個 Activity 啟動另一個 Activity 時,它們都會經歷生命周期轉換。第一個 Activity 停止運行并進入“已暫停”或“已停止”狀態,同時創建另一個 Activity。如果這些 Activity 共享保存到磁盤或其他位置的數據,必須要明確第一個 Activity 在創建第二個 Activity 之前并未完全停止。相反,啟動第二個 Activity 的過程與停止第一個 Activity 的過程重疊。
生命周期回調的順序已有明確定義,特別是當兩個 Activity 在同一個進程(應用)中,并且其中一個要啟動另一個時。以下是 Activity A 啟動 Activity B 時的操作發生順序:
Activity A 的
Activity B 的
然后,如果 Activity A 在屏幕上不再顯示,其
您可以利用這種可預測的生命周期回調順序管理從一個 Activity 到另一個 Activity 的信息轉換。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的android代理生命周期,了解 Activity 生命周期的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode 861. 翻转矩阵后的
- 下一篇: PHP动态验证,php-动态更改验证规则