活動生命週期

當使用者瀏覽、退出,再返回應用程式時 應用程式中的 Activity 個執行個體 處於生命週期的不同狀態 Activity 類別提供多個回呼 可使活動在狀態變更或 系統正在建立、停止或恢復活動或是刪除作業 活動所在程序。

在生命週期回呼方法中,您可以宣告活動方式 在使用者離開並重新進入活動時行動。舉例來說 若要建立串流影片播放器,您可以暫停影片,並終止 網路連線。當使用者回訪時 您可以重新連上網路,讓使用者從 相同位置

每次回呼都可讓您執行特定工作 適合特定狀態變更處理適當工作 能適度調整和處理轉換,讓應用程式更強大、效能更出色 例如,妥善實作生命週期回呼有助於應用程式 請避免:

  • 使用者接到來電或切換到其他來電時異常終止 也會影響應用程式使用情形
  • 在使用者未處於積極狀態時,佔用寶貴的系統資源 利用 Vertex AI Workbench 使用者
  • 使用者離開應用程式並返回時,失去進度 日後再匯入
  • 螢幕旋轉時,當機或遺失使用者的進度 適合橫向和直向螢幕使用

本文件將詳細說明活動生命週期。文件開頭 透過描述生命週期模式接下來,我們將說明每個回呼: 執行期間發生的情況及需要實作的項目 執行任務

然後簡單介紹活動之間的關係 並終止程序的安全漏洞 最後探討幾個有關 活動狀態。

有關處理生命週期的資訊,包括 最佳做法,請參閱 使用生命週期感知元件處理生命週期儲存 UI 狀態。 瞭解如何使用以下課程中的活動,建構出完善且品質媲美正式版的應用程式: 結合架構元件 應用程式架構指南

活動生命週期概念

如要在活動生命週期的不同階段之間瀏覽轉換,請 Activity 類別提供六種回呼的核心組合: onCreate(), onStart(), onResume(), onPause(), onStop()onDestroy()。系統會叫用 每個回呼都會進入新狀態。

圖 1 是這個模式的視覺呈現方式。

圖 1:更精簡的 活動生命週期的插圖。

當使用者開始離開活動時,系統會呼叫方法 去除活動在某些情況下,只有部分活動 會消失且仍會保留在記憶體中,例如使用者 其他應用程式。在這種情況下,活動仍可返回前景。

當使用者返回活動時 會從使用者停下來的地方繼續播放。除了少數例外情況 受限來源: 在背景執行時啟動活動

系統存在 終止特定程序及其中的活動,取決於狀態 發生當下的活動。如要進一步瞭解狀態與 要排除的安全漏洞,請參閱「活動狀態和從記憶體中排除」一節。

視活動的複雜程度而定,您可能不需要 實作所有生命週期方法不過,請務必 瞭解每個情境,並實作能讓應用程式運作的行為 自訂環境

生命週期回呼

本節將介紹 活動生命週期中使用的回呼方法。

部分動作屬於活動生命週期方法。不過,放置程式碼 這個外掛程式能實作 而非活動生命週期方法。如要這麼做,您需要 讓相依元件能夠感知生命週期瞭解如何 依附元件生命週期感知,請參閱 使用生命週期感知元件處理生命週期

onCreate()

您必須實作這個回呼,在系統首次建立 活動。建立活動時,活動會進入「Created」狀態。 在「onCreate()」中 執行基本的應用程式啟動邏輯 在整個活動生命週期中只會發生一次

舉例來說, onCreate() 實作可能會將資料繫結至清單,並將活動與 ViewModel, 並將部分類別範圍變數執行個體化這個方法會接收 savedInstanceState 參數,即 Bundle ,內含活動先前儲存狀態的物件。如果活動 從未存在,Bundle 物件的值為空值。

如果您的生命週期感知元件連接到 就會收到 ON_CREATE敬上 活動。系統會呼叫加上 @OnLifecycleEvent 註解的方法,以便偵測生命週期 元件可執行建立狀態所需的任何設定程式碼。

以下 onCreate() 方法的範例 顯示活動的基本設定,例如宣告使用者介面 (在 XML 版面配置檔案中定義)、定義成員變數,以及設定 一些使用者介面在這個範例中,XML 版面配置檔案會將 檔案的資源 ID R.layout.main_activity setContentView()

Kotlin

lateinit var textView: TextView

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

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

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

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

    // Initialize member TextView so it is available later.
    textView = findViewById(R.id.text_view)
}

// This callback is called only when there is a saved instance previously saved using
// onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally
// be restored 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 might 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 superclass onCreate to complete the creation of
    // the activity, like the view hierarchy.
    super.onCreate(savedInstanceState);

    // Recover the instance state.
    if (savedInstanceState != null) {
        gameState = savedInstanceState.getString(GAME_STATE_KEY);
    }

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

    // Initialize member TextView so it is available later.
    textView = (TextView) findViewById(R.id.text_view);
}

// This callback is called only when there is a saved instance previously saved using
// onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally
// be restored 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 might 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 檔案並傳遞至 setContentView() 以外,您還可以 可在活動程式碼中建立新的 View 物件,並建構 將新的 View 物件插入 ViewGroup。然後,您可以將 根層級 ViewGroupsetContentView()。 如要進一步瞭解如何建立使用者介面,請參閱 使用者介面說明文件。

你的活動不會保留在「建立」中 時間。onCreate() 方法執行完畢後,活動就會進入「Started」(啟動) 系統會呼叫 onStart()onResume() 方法 。

onStart()

當活動進入「已開始」狀態時,系統會 叫用 onStart()。 此呼叫會以 應用程式準備進入前景並進行互動。 舉例來說,這個方法是讓程式碼維護 UI 也要初始化

當活動轉換為「已啟動」狀態時,所有生命週期感知元件 對活動生命週期而言 ON_START 事件。

onStart() 方法完成時 而且就像「已建立」狀態一樣,活動不會 處於「已開始」狀態中此回呼完成後,活動會進入 Resumed 狀態,然後系統會叫用 onResume() 方法。

onResume()

當活動進入重新啟用狀態時,會進入前景並 系統會叫用 onResume() 回呼。這是應用程式的狀態 與使用者進行互動應用程式會保持這個狀態,直到發生任何問題為止 使用者遠離應用程式,例如能接聽來電的裝置、使用者 前往其他活動,或裝置螢幕關閉。

當活動進入「已恢復」狀態時,所有生命週期感知元件就會綁定 對活動生命週期而言 ON_RESUME敬上 活動。生命週期元件可讓所有需要執行 並在前景顯示元件,例如啟動相機 預覽。

發生幹擾事件時,活動會進入「已暫停」狀態 並叫用 onPause() 回呼。

如果活動回到 恢復狀態的重新啟用狀態,系統會再次呼叫 onResume() 方法。因此,請將 onResume():初始化發布期間的元件 onPause()並執行其他操作 每次活動進入 Resumed 時,都必須執行的初始化作業 時間。

以下是會存取相機的生命週期感知元件範例 元件會收到 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 事件。不過,在多視窗模式下 因此就算處於「暫停」狀態,也可以完全顯示舉例來說 應用程式處於多視窗模式,而使用者輕觸未開啟的視窗 包含您的活動,您的活動會變更為「已暫停」狀態。

如果發生以下情況: 您希望相機僅在應用程式重新啟用時啟用 (可見 並在前景啟動),然後初始化相機, ON_RESUME 個事件 如先前所示如果希望攝影機在活動期間保持啟用狀態 但狀態顯示為暫停,例如在多視窗模式下 在 ON_START 事件後初始化相機。

不過,有了相機 在你暫停活動期間進行活動時,可能會拒絕其他裝置存取攝影機 在多視窗模式下重新啟用應用程式。有時候必須 攝影機在活動暫停期間處於啟用狀態,但實際上可能會降低 以及整體使用者體驗

因此,請仔細思考 所以最好將容器中的共用系統資源 多視窗模式的上下文進一步瞭解如何支援多視窗模式 模式,請參閱「多視窗模式支援」。

無論您選擇執行哪一項建構事件 初始化作業,請務必使用對應的生命週期 活動釋出資源。如果您在 ON_START 事件,請在下列事件發生後釋出或終止: ON_STOP 事件。如果發生以下情況: 在 ON_RESUME 事件後執行初始化,並於 ON_PAUSE 事件。

上述程式碼片段會將相機初始化程式碼放在 生命週期感知元件您可以改為直接將這段程式碼放入活動中 生命週期回呼,例如 onStart()onStop(),但我們不建議您這樣做。新增此邏輯 並建構獨立的生命週期感知元件 跨多項活動執行多項作業,而不必重複程式碼如要瞭解如何建立生命週期感知元件,請參閱: 使用生命週期感知元件處理生命週期

onPause()

系統會呼叫此方法,做為第一個指標表示使用者退出 上的內容,但不一定表示該活動已經刪除。 它表示活動已不在前景,但實際上 仍會顯示 活動進入時段的可能原因有很多 狀態:

  • 中斷應用程式執行作業的事件,如相關章節所述 onResume() 回呼可暫停目前的活動,這是最常見的 確認是否屬於此情況
  • 在多視窗模式下,只有一個應用程式有焦點 系統會暫停所有其他應用程式。
  • 開啟新的半透明活動,例如對話方塊 會暫停元件涵蓋的活動只要 活動部分顯示,但沒有焦點, 就會維持暫停狀態

當活動進入「已暫停」狀態時,所有生命週期感知元件 對活動生命週期而言 ON_PAUSE 事件。此時 生命週期元件可能會停止任何不需要執行的功能 元件不在前景執行時 (例如停止相機) 預覽。

使用 onPause() 方法暫停或 調整無法繼續或可能繼續進行審核的作業; 當 Activity 處於「暫停」狀態,而您 很快就會恢復正常

您也可以使用 onPause() 方法 釋放系統資源、感應器 (如 GPS) 的控點,或者 會影響電池續航力,而你的活動在暫停期間,但使用者未 需要這些資訊

不過正如第 onResume() 節所述, 如果應用程式處於多視窗模式,則活動可能仍會完整顯示。 如要完整發布或調整,建議改用 onStop(),而不要使用 onPause() UI 相關資源和作業,可以更有效地支援多視窗模式。

以下的 LifecycleObserver 範例 回應 ON_PAUSE 事件與上述 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 事件。

onPause() 的執行過程非常短暫, 不一定足以執行儲存作業。為此 原因,請勿使用 onPause() 儲存應用程式或使用者 網路資料、發出網路呼叫或執行資料庫交易這類工作 然後再完成這項操作

而是在 YAML 檔案期間 onStop()。如要進一步瞭解 大約可以在 onStop(),請參閱下一節。進一步瞭解儲存 資料,請參閱儲存和還原狀態一節。

完成 onPause() 方法 並不表示活動會離開「已暫停」狀態。相反地 直到活動繼續或完全恢復狀態為止 不會向使用者顯示如果活動繼續,系統會再次叫用 onResume() 回呼。

如果 活動會從「已暫停」狀態返回「恢復」狀態, 在記憶體中常駐 Activity 執行個體 (喚回) 叫用 onResume() 時,就會發生這種情況。 在這種情況下,您不需要重新初始化任何在 。如果活動 系統會呼叫 onStop()

onStop()

使用者不再看得到您的活動時,活動就會進入 Stopped 狀態,而系統會叫用 onStop() 回呼。當新啟動的活動覆蓋整個螢幕時,就可能發生這種情況。 系統也會呼叫 onStop() 會在活動執行完畢且即將終止時啟動。

當活動轉換為「已停止」狀態時,所有生命週期感知元件 對活動生命週期而言 ON_STOP 事件。此時 生命週期元件可能會停止任何不需要執行的功能 並在畫面上不會顯示元件時

onStop() 方法中,釋放或調整 不需要的資源。舉例來說,您的應用程式 暫停動畫,或從精細位置更新切換至概略位置更新。使用 onStop() 取代 onPause() 這表示即使使用者是在多視窗模式中查看活動,UI 相關作業仍會繼續進行 模式。

另請使用 onStop() 來執行會耗用大量 CPU 資源的關閉作業。舉例來說 無法找出更適合將資訊儲存至資料庫的時間 這就可能會在 onStop() 中達到 以下範例為 onStop(),可儲存 建立 BERT 版本

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 物件會保留在記憶體中:其會保留所有狀態 但不會附加至視窗管理員。當活動出現時 就會記住這項資訊

您不一定要 重新初始化任何回呼方法期間建立的元件 直到恢復狀態為止系統也會追蹤目前 版面配置中每個 View 物件的狀態,因此如果 使用者在 EditText 小工具中輸入文字, 系統會保留這類內容,因此您不需要儲存及還原。

注意: 活動停止後,系統會 如果系統可能刪除包含活動的程序 必須復原記憶體 即使系統在活動期間刪除程序 停止後,系統仍會保留 View 的狀態 物件,例如 EditText 小工具中的文字 Bundle:鍵/值組合的 blob— 並還原鍵/值組合 如果使用者返回活動適用對象 如要進一步瞭解如何還原使用者返回的活動,請參閱 參閱儲存與還原狀態一節。

在「已停止」狀態下,活動會返回以與 或活動完成執行後消失。如果活動 返回,系統會叫用 onRestart()。 如果 Activity 執行完畢,系統會呼叫 onDestroy()

onDestroy()

系統會先呼叫 onDestroy(),再呼叫 就會遭到刪除系統會基於以下兩個原因叫用此回呼:

  1. 使用者 或因為 finish() 是 會在活動上呼叫
  2. 因設定而暫時刪除活動 變更,例如裝置旋轉或進入多視窗模式。

當活動轉換為已刪除狀態時,所有生命週期感知元件 對活動生命週期而言 ON_DESTROY 事件。此時 生命週期元件可以清除必要內容 Activity 已刪除。

如要判斷類別遭到刪除的原因,請不要在 Activity 中加入邏輯, 使用 ViewModel 物件來包含 Activity的相關檢視資料。如果 Activity 已重新建立 由於設定變更,ViewModel 無須採取任何行動,因為 該物件會保留下來,並傳遞至下一個 Activity 例項。

如果未重新建立 Activity,則 ViewModel 具有 呼叫 onCleared() 方法,其中 可以清除資源刪除前所需的任何資料您可以運用 isFinishing() 方法,增加圍繞地圖邊緣的邊框間距。

如果活動結束,onDestroy() 則是最終生命週期回呼 活動接收。如果設定結果呼叫 onDestroy() 變更,系統會立即建立一個新的活動例項,然後呼叫 onCreate() 並建立新的執行個體

onDestroy() 回呼會釋出所有先前未釋出的資源 回呼,例如 onStop()

活動狀態和從記憶體中排除

系統會在需要釋出 RAM 時終止程序。系統的可能性 終止特定程序取決於處理當時的程序狀態。程序狀態 進而取決於程序中執行的活動狀態。 表 1 顯示程序狀態、活動之間的關係 以及系統終止程序的可能性。這個表格僅適用於程序並非執行其他類型的 應用程式元件

被殺害的可能性 處理狀態 最終活動狀態
極低 前景 (正在或即將聚焦) 已重新啟用
顯示 (無焦點) 已開始/已暫停
較高 背景 (隱藏) 已停止
最高 空白 已刪除

表 1. 程序生命週期和活動狀態之間的關係。

系統不會直接終止活動來釋放記憶體。相反地 終止執行活動的程序,而不僅刪除活動 但在這個程序中運作的所有其他項目如果想瞭解 並在系統終止程序時還原活動的 UI 狀態 請參閱儲存和還原狀態一節。

使用者也可以使用「應用程式管理員」中的 [設定] 部分 終止對應的應用程式

如要進一步瞭解程序,請參閱 處理程序與執行緒 總覽頁面

儲存及還原暫時性 UI 狀態

使用者會預期活動的 UI 狀態在整個 例如旋轉或切換至多視窗模式 不過,在這類設定下,系統預設會刪除活動 系統會清除儲存在活動例項中的任何 UI 狀態。

同樣地,若使用者暫時希望 UI 狀態暫時維持不變 先從您的應用程式切換到其他應用程式,再返回您的應用程式 然而,系統可能會在 使用者離開,您的活動即會停止。

系統限制刪除活動時,保留 使用者的暫時性 UI 狀態 ViewModel onSaveInstanceState()、 和/或本機儲存空間進一步瞭解與系統相較下的使用者期望 以及如何有效保留不同應用程式的複雜 UI 狀態資料 系統啟動的活動和程序死亡,詳情請參閱 儲存 UI 狀態。

本節概述執行個體狀態,以及如何實作 onSaveInstance() 方法:活動本身的回呼。如果您的 UI 資料輕巧,您可以單獨使用 onSaveInstance() 來保留 UI 狀態。 但因為 onSaveInstance() 會產生序列化/去序列化費用, 大多數情況下,請同時使用 ViewModelonSaveInstance(),因為 概述於 儲存 UI 狀態

注意: 如要進一步瞭解設定變更,請參閱如何限制活動 視需要重新建立,以及回應設定變更時 如要查看系統和 Jetpack Compose,請參閱 「處理設定變更」頁面。

執行個體狀態

在幾種情況下,您的活動會因為正常應用程式而刪除 行為,例如使用者按下「返回」按鈕或您的活動時 會藉由呼叫 finish()敬上 方法。

當使用者按下返回按鈕,藉此刪除活動時的活動。 或活動自行完成,而系統和使用者的概念 該 Activity 執行個體會永久刪除。在以下 使用者的期望符合系統行為, 不需要額外採取任何行動

不過,如果系統因為系統限制 (例如 仍會造成設定變更或記憶體壓力 Activity 執行個體不存在時,系統會記住執行個體存在。如果使用者嘗試 返回活動,系統就會建立新的例項 透過一組用來描述活動狀態的資料活動 刪除圖片的時間

系統用來還原 先前狀態稱為例項狀態。這是一系列的 鍵/值組合儲存在 Bundle 物件中。根據預設, 系統會使用 Bundle 例項狀態來儲存資訊 活動版面配置中的每個 View 物件,例如 輸入文字值 EditText 小工具。

所以 系統會刪除並重新建立活動執行個體,版面配置的狀態會是 已還原至先前的狀態,您不需要使用任何程式碼。不過, 活動可能有您要還原的狀態資訊,例如 追蹤使用者活動進度的成員變數。

注意: 為了讓 Android 系統還原 您活動中的資料檢視都必須有一個由 android:id 屬性。

Bundle 物件不適用於保留數量超過 資料量不大,因為需要在主執行緒上序列化,並耗用 系統處理記憶體如要保留極少量資料 採取綜合方法來保存資料,使用永久本機儲存空間 儲存空間、onSaveInstanceState() 方法和 ViewModel 類別,如 所述 儲存 UI 狀態

使用 onSaveInstanceState() 儲存簡單、輕量的 UI 狀態

當您的活動開始停止時,系統會呼叫 onSaveInstanceState()敬上 方法,讓活動可以將狀態資訊儲存至例項狀態 軟體包。此方法的預設實作方式可節省 活動檢視區塊階層的狀態相關資訊,例如 EditText 小工具內的文字,或 ListView小工具。

如要為活動儲存其他例項狀態資訊,請覆寫 onSaveInstanceState() 並將鍵/值組合新增至儲存的 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);
}

注意: onSaveInstanceState()不是 在使用者明確關閉活動時呼叫,或者在其他情況下 系統已呼叫 finish()

如要儲存永久資料 (例如使用者偏好設定或資料庫資料), 在前景執行的活動時,把握適當機會。 如果沒有這種商機,請在 onStop() 方法,增加圍繞地圖邊緣的邊框間距。

使用已儲存的執行個體狀態還原活動 UI 狀態

當系統在活動先前刪除後重新建立活動時 可以從 Bundle 復原已儲存的例項狀態 系統會將這些資訊傳送到你的活動兩者 onCreate() onRestoreInstanceState() 回呼方法會接收與回呼方法相同的 Bundle,其中包含 執行個體狀態資訊

因為 onCreate() 方法 呼叫系統是否建立新的活動例項 或重新建立先前的資源,您必須檢查狀態是 Bundle 在嘗試讀取前是空值。若為空值 請建立新的活動例項,而不是還原 全部刪除了

下列程式碼片段說明如何還原 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.
    }
    // ...
}

而不是在執行期間還原狀態 onCreate(),您可以選擇 onRestoreInstanceState(),系統會在 onStart() 方法。系統呼叫 onRestoreInstanceState() 因此當您還原已儲存的狀態時 不需要檢查 Bundle 是否為空值。

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() 因此預設實作方式可以還原檢視區塊階層的狀態。

瀏覽不同活動

應用程式可能會在活動期間多次進入及結束活動, 應用程式的生命週期,例如使用者輕觸裝置的返回按鈕時 或者活動會啟動其他活動

這個區段 涵蓋了順利實作活動轉換的必要主題。 這些主題包括從其他活動開始活動、儲存活動 以及還原活動狀態

開始其他活動

活動通常會在某個時間點開始另一個活動。這項需求 舉例來說,如果應用程式需要從目前的畫面移至 新的 Pod

視您的活動是否希望新活動傳回結果而定 即將開始,您要使用 startActivity() 方法,或 startActivityForResult() 方法。無論是哪一種情況,您都需要傳入 Intent 物件。

Intent 物件會指定 您想啟動的活動,或描述您要執行的動作類型。 系統會為您選取適當的活動 不同應用程式Intent 物件可以 也包含要啟動的活動所使用的少量資料。 如要進一步瞭解 Intent 類別,請參閱 意圖和意圖 篩選器

startActivity()

如果新啟動的活動不需傳回結果,目前活動即可啟動 方法是呼叫 startActivity() 方法。

在自己的應用程式中作業時,您通常需要啟動已知活動。 舉例來說,下列程式碼片段說明如何啟動名為 SignInActivity

Kotlin

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

Java

Intent intent = new Intent(this, SignInActivity.class);
startActivity(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);

新增至意圖的 EXTRA_EMAIL 是 要接收電子郵件的電子郵件地址。電子郵件應用程式 回應此意圖,它會讀取在額外項目中提供的字串陣列 會將地址放在「收件者」輸入電子郵件撰寫表單的欄位在本 中斷電子郵件應用程式的活動,也啟動使用者完成時 就會恢復活動。

startActivityForResult()

有時候,您可能會希望在活動結束後取得結果。舉例來說 可讓使用者在聯絡人清單中選擇某人的活動。結束時,它會傳回 選出的人物方法是呼叫 startActivityForResult(Intent, int) 方法,其中 整數參數代表呼叫

這個 ID 的作用是區分 startActivityForResult(Intent, int) 相同活動這不是全域 ID 而不會與其他應用程式或活動發生衝突。搜尋結果會從您的 onActivityResult(int, int, Intent) 方法。

子項活動結束時,可以呼叫 setResult(int) 以便 將資料傳回至父項 子活動必須提供結果代碼,可以是標準結果 RESULT_CANCELEDRESULT_OK 或任何自訂值 開始時間:RESULT_FIRST_USER

此外, 子項活動可以選擇傳回 Intent 物件,其中包含所需的任何其他資料。父項活動會使用 onActivityResult(int, int, Intent) 方法,以及父項活動最初的整數識別碼 的呼叫,以便接收資訊。

如果子項活動因任何原因 (例如停止運作) 失敗,父項活動 活動會收到包含代碼 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) {
                    // A contact was picked. Display it to the user.
                    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. Display it to the user.
                 startActivity(new Intent(Intent.ACTION_VIEW, data));
             }
         }
     }
 }

協調活動

當一個活動啟動另一項活動時,兩個活動都會經歷生命週期轉換。 第一個活動會停止運作,然後進入「已暫停」或「已停止」狀態,另一個活動則進入「已暫停」或「已停止」狀態 系統會建立活動。假如這些活動會共用儲存至磁碟或其他位置的資料, 重要的是,第一個活動不會在第二次活動之前完全停止 相反地,第二個解決方案的啟動程序 與 並且停止第一個

生命週期回呼的順序已明確定義,尤其是當兩個活動 也就是同一應用程式,另一個則啟動另一個應用程式。以下是發生作業的順序 活動 A 啟動活動 B 時:

  1. 系統會執行活動 A 的 onPause() 方法。
  2. 活動 B 的 onCreate()onStart()onResume() 方法會依序執行。 活動 B 現在是以使用者為重。
  3. 如果活動 A 不再顯示於螢幕上,則會執行其 onStop() 方法。

這一系列生命週期回呼可讓您管理 在活動之間取得資訊