アクティビティのライフサイクル

アクティビティは Android アプリケーションの基礎となる構成要素であり、さまざまな状態が存在します。 アクティビティ ライフサイクルはインスタンス化から始まり、破棄で終わり、その間には多くの状態があります。 アクティビティの状態が変化すると、適切なライフサイクル イベント メソッドが呼び出され、状態がまもなく変化することがアクティビティに通知され、アクティビティはその変更に適応するためのコードを実行できます。 この記事では、アクティビティのライフサイクルを調べます。また、アクティビティが、適切に動作する信頼性の高いアプリケーションの一部となるために、各状態の変更で担う責任について説明します。

アクティビティ ライフサイクルの概要

アクティビティは、Android に固有のもので、通常とは異なるプログラミング概念です。 従来のアプリケーション開発では、通常、アプリケーションを起動するために実行される静的なメイン メソッドがあります。 しかし、Android の場合は違います。Android アプリケーションの場合、アプリケーション内で登録されているどのアクティビティを介してでも起動できます。 実際には、ほとんどのアプリケーションには、アプリケーション エントリ ポイントとして指定された特定のアクティビティのみが含まれます。 ただし、アプリケーションがクラッシュした場合や、OS によって終了された場合、OS は最後に開いているアクティビティか、前のアクティビティ スタックのいずれかのアクティビティで、アプリケーションの再起動を試みることができます。 さらに、OS はアクティブでないときにアクティビティを一時停止し、メモリが不足している場合は再利用することがあります。 アプリケーションがアクティビティの再起動時にその状態を正しく復元できるように、注意深く検討する必要があります。そのアクティビティが以前のアクティビティのデータに依存している場合は、特にそうです。

アクティビティ ライフサイクルは、アクティビティのライフサイクル全体にわたって OS が呼び出すメソッドのコレクションとして実装されます。 これらのメソッドを使用すると、開発者はアプリケーションの状態とリソース管理の要件を満たすために必要な機能を実装できます。

アプリケーション開発者が各アクティビティの要件を分析し、アクティビティ ライフサイクルによって公開されるメソッドを実装する必要があるかどうかを判断することは非常に重要です。 これを行わないと、アプリケーションが不安定になり、クラッシュし、リソースが肥大化する原因となります。また、場合によっては、基になる OS が不安定になる可能性もあります。

この章では、以下を含むアクティビティ ライフサイクルについて詳しく説明します。

  • アクティビティの状態
  • ライフサイクル メソッド
  • アプリケーションの状態を保持する

このセクションには、アクティビティ ライフサイクルで状態を効率的に保存する方法に関する実用的な例を示すチュートリアルも含まれています。 この章の終わりまでに、アクティビティ ライフサイクルと、Android アプリケーションでアクティビティをサポートする方法を理解できます。

アクティビティのライフサイクル

Android のアクティビティ ライフサイクルは、開発者にリソース管理フレームワークを提供する Activity クラス内で公開されるメソッドのコレクションで構成されます。 このフレームワークを使用すると、開発者はアプリケーション内の各アクティビティの固有の状態管理要件を満たし、リソース管理を適切に処理できます。

アクティビティの状態

Android OS は、アクティビティをその状態に基づいて調整します。 これにより、Android が使用されなくなったアクティビティを識別できるため、OS がメモリとリソースを再利用できるようになります。 次の図は、アクティビティが有効期間中に通過できる状態を示しています。

Activity states diagram

これらの状態は、主に次の 4 つのグループに分割できます。

  1. アクティブまたは実行中 – アクティビティは、フォアグラウンド (アクティビティ スタックの最上位としても知られている) にある場合、アクティブまたは実行中と見なされます。 これは Android で最も優先度の高いアクティビティと見なされるため、極端な状況でのみ OS によって強制終了されます。たとえば、アクティビティがデバイスで使用できる以上のメモリを使用しようとしたために、UI が応答しなくなる可能性がある場合などです。

  2. 一時停止 – デバイスがスリープ状態になった場合、またはアクティビティがまだ表示されているが、フルサイズではないか透過的な新しいアクティビティによって部分的に非表示になっている場合、アクティビティは一時停止と見なされます。 一時停止したアクティビティはまだ有効です。つまり、すべての状態とメンバー情報が保持され、ウィンドウ マネージャーにアタッチされた状態が保たれます。 これは Android で 2 番目に優先度の高いアクティビティと見なされます。そのため、このアクティビティを強制終了すると、アクティブ/実行中アクティビティの安定性と応答性を維持するために必要なリソース要件を満たす場合にのみ、OS によって強制終了されます。

  3. 停止/バックグラウンド化 – 別のアクティビティによって完全に隠されたアクティビティは、停止またはバックグラウンドにあると見なされます。 停止されたアクティビティは、状態とメンバーの情報をできるだけ長く保持しようとしますが、停止されたアクティビティは 3 つの状態の中で最も優先度が低いと見なされるため、OS は優先順位の高いアクティビティのリソース要件を満たすために、最初にこの状態のアクティビティを強制終了します。

  4. 再起動 – ライフサイクルで一時停止から停止までのいずれかの場所にあるアクティビティは、Android によってメモリから削除される可能性があります。 ユーザーがアクティビティに戻った場合は、再起動し、以前に保存した状態に復元してから、ユーザーに表示する必要があります。

構成の変更に対応するアクティビティを再作成する

さらに複雑なことに、Android では、構成の変更が行われるため、作業の妨害となります。 構成の変更は、迅速なアクティビティの破棄/再作成サイクルで、アクティビティの構成が変更されたときに発生します。たとえば、デバイスが回転したとき (つまり、アクティビティを横モードまたは縦モードで再度組み込む必要がある場合)、キーボードが表示されたとき (つまり、アクティビティにサイズを変更する機会が与えられる)、またはデバイスが他のデバイスと共にドックに配置されたときなどです。

構成の変更は、アクティビティの停止と再起動中に発生するのと同じアクティビティ状態の変更を引き続き発生させます。 ただし、アプリケーションの応答性を維持し、構成の変更中にアプリケーションが適切に実行されるようにするには、できるだけ早く処理することが重要です。 このため、Android には、構成の変更中に状態を保持するために使用できる特定の API があります。 これについては、後の「ライフサイクル全体にわたって状態を管理する」セクションで説明します。

アクティビティ ライフサイクルのメソッド

Android SDK と、拡張機能を利用した Xamarin.Android フレームワークは、アプリケーション内のアクティビティの状態を管理するための強力なモデルを提供します。 アクティビティの状態が変化するとき、アクティビティは OS によって通知され、そのアクティビティに対して特定のメソッドが呼び出されます。 次の図では、これらのメソッドをアクティビティ ライフサイクルに関連して表示しています。

Activity Lifecycle flowchart

開発者は、アクティビティ内でこれらのメソッドをオーバーライドすることで、状態の変更を処理できます。 ただし、注意すべき点として、すべてのライフサイクル メソッドが UI スレッドで呼び出され、OS による次の UI 作業 (現在のアクティビティの非表示、新しいアクティビティの表示など) の実行をブロックします。そのため、アプリケーションのパフォーマンスを高めるために、これらのメソッドのコードはできるだけ短くする必要があります。 実行時間の長いタスクは、バックグラウンド スレッドで実行する必要があります。

これらの各ライフサイクル メソッドとその使用方法を調べてみましょう。

OnCreate メソッド

OnCreate は、アクティビティの作成時に最初に呼び出されるメソッドです。 OnCreate は、アクティビティから要求される可能性があるスタートアップ初期化を実行するために、常にオーバーライドされます。たとえば、次のようなものがあります。

  • ビューの作成
  • 変数の初期化
  • 静的データをリストにバインドする

OnCreateBundle パラメーターを受け取ります。これは、アクティビティ間で状態情報とオブジェクトを保存および渡すための辞書です。バンドルが null でない場合は、アクティビティが再起動中であり、前のインスタンスから状態を復元する必要があることを示しています。 次のコードは、バンドルから値を取得する方法を示しています。

protected override void OnCreate(Bundle bundle)
{
   base.OnCreate(bundle);

   string intentString;
   bool intentBool;

   if (bundle != null)
   {
      intentString = bundle.GetString("myString");
      intentBool = bundle.GetBoolean("myBool");
   }

   // Set our view from the "main" layout resource
   SetContentView(Resource.Layout.Main);
}

OnCreate が完了すると、Android は OnStart を呼び出します。

OnStart

OnStart は、OnCreate の完了後に常にシステムによって呼び出されます。 アクティビティ内のビューの現在の値を更新するなど、アクティビティが表示される直前に特定のタスクを実行する必要がある場合、アクティビティはこのメソッドをオーバーライドできます。 Android は、このメソッドの直後に OnResume を呼び出します。

OnResume

アクティビティがユーザーとの対話を開始する準備ができたら、システムは OnResume を呼び出します。 アクティビティは、次のようなタスクを実行するために、このメソッドをオーバーライドする必要があります。

  • フレーム レートの増加 (ゲーム開発の一般的なタスク)
  • 起動アニメーション
  • GPS の更新の待機
  • 関連するアラートやダイアログの表示
  • 外部イベント ハンドラーの接続

例として、次のコード スニペットは、カメラを初期化する方法を示しています。

protected override void OnResume()
{
    base.OnResume(); // Always call the superclass first.

    if (_camera==null)
    {
        // Do camera initializations here
    }
}

OnPause で実行される操作はすべて OnResume で元に戻す必要があるため、OnResume は重要です。これは、アクティビティを元の状態に戻すときに OnPause の後に実行することが保証されている唯一のライフサイクル メソッドだからです。

OnPause

OnPause は、システムがアクティビティをバックグラウンドに配置しようとしている場合、またはアクティビティが部分的に隠された場合に呼び出されます。 アクティビティは、次の操作を行う必要がある場合に、このメソッドをオーバーライドする必要があります。

  • 保存されていない変更を永続的なデータにコミットする

  • リソースを消費する他のオブジェクトを破棄またはクリーンする

  • フレーム レートを下げてアニメーションを一時停止する

  • 外部イベント ハンドラーまたは通知ハンドラー (つまり、サービスに関連付けられているもの) の登録を解除する。 これは、アクティビティ メモリ リークを防ぐために行う必要があります。

  • 同様に、アクティビティにダイアログやアラートが表示されている場合は、.Dismiss() メソッドを使用してクリーンする必要があります。

たとえば、次のコード スニペットは、一時停止中にアクティビティでカメラを使用できないため、カメラを解放します。

protected override void OnPause()
{
    base.OnPause(); // Always call the superclass first

    // Release the camera as other activities might need it
    if (_camera != null)
    {
        _camera.Release();
        _camera = null;
    }
}

OnPause の後に、次の 2 つのライフサイクル メソッドが呼び出される可能性があります。

  1. OnResume は、アクティビティがフォアグラウンドに返される場合に呼び出されます。
  2. OnStop は、アクティビティがバックグラウンドで配置されている場合に呼び出されます。

OnStop

OnStop は、アクティビティがユーザーに表示されなくなったときに呼び出されます。 これは、次のいずれかの場合に発生します。

  • 新しいアクティビティが開始され、このアクティビティがカバーされている。
  • 既存のアクティビティがフォアグラウンドに移動している。
  • アクティビティが破棄されている。

OnStop は、メモリ不足の状況で常に呼び出されるとは限りません。たとえば、リソースに対して Android が不足していて、アクティビティを適切にバックグラウンドで実行できない場合などです。 このため、破棄のためにアクティビティを準備するときに OnStop の呼び出しに頼らないのが最善です。 この後に呼び出される可能性のあるライフサイクル メソッドは、アクティビティが終了した場合は OnDestroy、アクティビティがユーザーと対話するために戻ってくる場合は OnRestart です。

OnDestroy

OnDestroy は、アクティビティ インスタンスが破棄されてメモリから完全に削除される前に、アクティビティ インスタンスで呼び出される最後のメソッドです。 極端な状況では、Android はアクティビティをホストしているアプリケーション プロセスを強制終了する可能性があり、結果として OnDestroy が呼び出されません。 ほとんどのクリーンアップとシャットダウンが OnPause メソッドと OnStop メソッドで実行されているため、ほとんどのアクティビティでこのメソッドは実装されません。 通常、OnDestroy メソッドは、リソースがリークする可能性のある実行時間の長いタスクをクリーンするためにオーバーライドされます。 この例として、OnCreate で開始されたバックグラウンド スレッドが考えられます。

アクティビティが破棄された後に呼び出されるライフサイクル メソッドはありません。

OnRestart

OnRestart は、アクティビティが停止した後、再び開始される前に呼び出されます。 ユーザーがアプリケーションのアクティビティ中にホーム ボタンを押した場合が、この良い例です。 これが発生すると、OnPause メソッドと、その後に OnStop メソッドが呼び出されます。アクティビティはバックグラウンドに移動しますが、破棄はされません。 ユーザーがタスク マネージャーまたは同様のアプリケーションを使用してアプリケーションを復元した場合、Android はアクティビティの OnRestart メソッドを呼び出します。

OnRestart で実装する必要があるロジックの種類に関する一般的なガイドラインはありません。 これは、アクティビティが作成されているか再起動されているかに関係なく OnStart が常に呼び出されるためです。そのため、アクティビティに必要なすべてのリソースは、OnRestart ではなく OnStart で初期化する必要があります。

OnRestart の後に呼び出される次のライフサイクル メソッドは OnStart です。

[戻る] とHome

多くの Android デバイスには、[戻る] ボタンと [ホーム] ボタンの 2 つの異なるボタンがあります。 Android 4.0.3 の次のスクリーンショットでこの例を確認できます。

Back and Home buttons

2 つのボタンは、アプリケーションをバックグラウンドに配置する場合と同じ効果を持っているように見えますが、微妙な違いがあります。 ユーザーが [戻る] ボタンをクリックすると、アクティビティが完了したことが Android に通知されます。 Android はアクティビティを破棄します。 これに対し、ユーザーが [ホーム] ボタンをクリックすると、アクティビティは単にバックグラウンドに配置されルだけです。Android はアクティビティを強制終了しません。

ライフサイクル全体にわたって状態を管理する

アクティビティが停止または破棄されると、システムは後でリハイドレートするためにアクティビティの状態を保存する機会を提供します。 この保存された状態は、インスタンス状態と呼ばれます。 Android には、アクティビティのライフサイクル中にインスタンスの状態を保存するための次の 3 つのオプションが用意されています。

  1. Android が状態の保存に使用するバンドルと呼ばれる Dictionary にプリミティブ値を保存する。

  2. ビットマップなどの複雑な値を保持するカスタム クラスを作成する。 Android では、このカスタム クラスを使用して状態を保存します。

  3. 構成の変更のライフサイクルを回避し、アクティビティの状態を保持する完全な責任を負う。

このガイドでは、最初の 2 つのオプションについて説明します。

バンドル状態

インスタンスの状態を保存するための主なオプションは、バンドルと呼ばれるキー/値ディクショナリ オブジェクトを使用することです。 メソッドがパラメーターとしてバンドルを渡す OnCreate アクティビティが作成されると、このバンドルを使用してインスタンスの状態を復元できることを思い出してください。 キーと値のペア (ビットマップなど) にすばやくまたは簡単にシリアル化できない、より複雑なデータにバンドルを使用することはお勧めしません。これはむしろ、文字列のような単純な値に使用する必要があります。

アクティビティには、バンドル内のインスタンス状態の保存と取得に役立つメソッドが用意されています。

  • OnSaveInstanceState – これは、アクティビティが破棄されるときに Android によって呼び出されます。 アクティビティは、キー/値の状態項目を保持する必要がある場合に、このメソッドを実装できます。

  • OnRestoreInstanceState – これは OnCreate メソッドの完了後に呼び出され、初期化が完了した後にアクティビティが状態を復元する別の機会を提供します。

次の図は、これらのメソッドがどのように使用されるかを示しています。

Bundle states flowchart

OnSaveInstanceState

アクティビティが停止すると、OnSaveInstanceState が呼び出されます。 アクティビティが状態を保存できるバンドル パラメーターを受け取ります。 デバイスで構成の変更が発生した場合、アクティビティは渡された Bundle オブジェクトを使用して、OnSaveInstanceState をオーバーライドすることでアクティビティの状態を保持できます。 表すクレソン、ダン橄欖岩製品構文解析木作法:

int c;

protected override void OnCreate (Bundle bundle)
{
  base.OnCreate (bundle);

  this.SetContentView (Resource.Layout.SimpleStateView);

  var output = this.FindViewById<TextView> (Resource.Id.outputText);

  if (bundle != null) {
    c = bundle.GetInt ("counter", -1);
  } else {
    c = -1;
  }

  output.Text = c.ToString ();

  var incrementCounter = this.FindViewById<Button> (Resource.Id.incrementCounter);

  incrementCounter.Click += (s,e) => {
    output.Text = (++c).ToString();
  };
}

上記のコードは、incrementCounter というボタンがクリックされたときに c という整数をインクリメントし、output という TextView に結果を表示します。 構成の変更が発生した場合 (デバイスが回転した場合など) は、bundlenull になるため、上記のコードの c の値が失われます。これを次の図に示します。

Display does not show previous value

この例の c の値を保持するために、アクティビティは OnSaveInstanceState をオーバーライドし、次に示すように値をバンドルに保存します。

protected override void OnSaveInstanceState (Bundle outState)
{
  outState.PutInt ("counter", c);
  base.OnSaveInstanceState (outState);
}

デバイスが新しい向きに回転されると、整数がバンドルに保存され、行と共に取得されます。

c = bundle.GetInt ("counter", -1);

Note

ビュー階層の状態を保存できるように、常に OnSaveInstanceState の基本実装を呼び出す必要があります。

ビュー状態

OnSaveInstanceState のオーバーライドは、前の例のカウンターなど、向きの変化におけるアクティビティの一時的なデータを保存する際に適したメカニズムです。 ただし、OnSaveInstanceState の既定の実装では、ID が割り当てられている限り、すべてのビューの UI に一時的なデータが保存されます。 たとえば、次のように、アプリに XML で定義された EditText 要素があるとします。

<EditText android:id="@+id/myText"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"/>

EditText コントロールには id が割り当てられているため、ユーザーがデータを入力してデバイスを回転させると、次に示すようにデータが表示されます。

Data is preserved in landscape mode

OnRestoreInstanceState

OnRestoreInstanceStateOnStart の後に呼び出されます。 以前の OnSaveInstanceState でバンドルに保存されたすべての状態を復元する機会をアクティビティに提供します。 ただし、これは OnCreate に提供されるバンドルと同じです。

次のコードは、状態を OnRestoreInstanceState に復元する方法を示しています。

protected override void OnRestoreInstanceState(Bundle savedState)
{
    base.OnRestoreInstanceState(savedState);
    var myString = savedState.GetString("myString");
    var myBool = savedState.GetBoolean("myBool");
}

このメソッドは、状態を復元する必要がある場合に柔軟性を提供するために存在します。 インスタンスの状態を復元する前に、すべての初期化が完了するまで待つ方が適切な場合があります。 さらに、既存のアクティビティのサブクラスは、インスタンスの状態から特定の値のみを復元しようとする場合があります。 多くの場合、OnRestoreInstanceState をオーバーライドする必要はありません。ほとんどのアクティビティは、OnCreate に提供されたバンドルを使用して状態を復元できるからです。

Bundle を使用して状態を保存する例については、「チュートリアル - アクティビティの状態を保存する」をご覧ください。

バンドルの制限事項

OnSaveInstanceState を使用すると一時的なデータを簡単に保存できますが、次のような制限事項があります。

  • すべてのケースで呼び出されるわけではない。 たとえば、[ホーム] キーまたは [戻る] キーを押してアクティビティを終了しても、OnSaveInstanceState は呼び出されません。

  • OnSaveInstanceState に渡されるバンドルは、イメージなどの大きなオブジェクト用には設計されていません。 大きなオブジェクトの場合、以下で説明するように、OnRetainNonConfigurationInstance からオブジェクトを保存することをお勧めします。

  • バンドルを使用して保存されたデータはシリアル化されるため、遅延が発生する可能性があります。

バンドル状態は、メモリをあまり使用しない単純なデータに役立ちます。一方、構成以外のインスタンス データは、より複雑なデータや、Web サービス呼び出しや複雑なデータベース クエリから取得するのにコストがかかるデータに役立ちます。 構成以外のインスタンス データは、必要に応じてオブジェクトに保存されます。 次のセクションでは、構成の変更によってより複雑なデータ型を保持する方法としての OnRetainNonConfigurationInstance について説明します。

複雑なデータを永続化する

Android では、バンドル内のデータの永続化に加えて、OnRetainNonConfigurationInstance をオーバーライドし、保持するデータを含む Java.Lang.Object のインスタンスを返すことによるデータの保存もサポートされています。 OnRetainNonConfigurationInstance を使用して状態を保存する主な利点は 2 つあります。

  • OnRetainNonConfigurationInstance から返されるオブジェクトは、より大きく複雑なデータ型で適切に実行されます。メモリがこのオブジェクトを保持するからです。

  • OnRetainNonConfigurationInstance メソッドは、オンデマンドで、必要な場合にのみ呼び出されます。 これは、手動キャッシュを使用するよりも経済的です。

OnRetainNonConfigurationInstance の使用は、Web サービス呼び出しなど、データを複数回取得するコストがかかるシナリオに適しています。 たとえば、Twitter を検索する次のコードを考えてみましょう。

public class NonConfigInstanceActivity : ListActivity
{
  protected override void OnCreate (Bundle bundle)
  {
    base.OnCreate (bundle);
    SearchTwitter ("xamarin");
  }

  public void SearchTwitter (string text)
  {
    string searchUrl = String.Format("http://search.twitter.com/search.json?" + "q={0}&rpp=10&include_entities=false&" + "result_type=mixed", text);

    var httpReq = (HttpWebRequest)HttpWebRequest.Create (new Uri (searchUrl));
    httpReq.BeginGetResponse (new AsyncCallback (ResponseCallback), httpReq);
  }

  void ResponseCallback (IAsyncResult ar)
  {
    var httpReq = (HttpWebRequest)ar.AsyncState;

    using (var httpRes = (HttpWebResponse)httpReq.EndGetResponse (ar)) {
      ParseResults (httpRes);
    }
  }

  void ParseResults (HttpWebResponse httpRes)
  {
    var s = httpRes.GetResponseStream ();
    var j = (JsonObject)JsonObject.Load (s);

    var results = (from result in (JsonArray)j ["results"] let jResult = result as JsonObject select jResult ["text"].ToString ()).ToArray ();

    RunOnUiThread (() => {
      PopulateTweetList (results);
    });
  }

  void PopulateTweetList (string[] results)
  {
    ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results);
  }
}

このコードは、Web から JSON 形式の結果を取得し、解析してから、結果を一覧に表示します。このことを次のスクリーンショットに示します。

Results displayed on screen

構成の変更が発生した場合 (デバイスのローテーション時など)、コードはこのプロセスを繰り返します。 最初に取得した結果を再利用し、不要で冗長なネットワーク呼び出しを引き起こさないように、次に示すように OnRetainNonconfigurationInstance を使用して結果を保存できます。

public class NonConfigInstanceActivity : ListActivity
{
  TweetListWrapper _savedInstance;

  protected override void OnCreate (Bundle bundle)
  {
    base.OnCreate (bundle);

    var tweetsWrapper = LastNonConfigurationInstance as TweetListWrapper;

    if (tweetsWrapper != null) {
      PopulateTweetList (tweetsWrapper.Tweets);
    } else {
      SearchTwitter ("xamarin");
    }

    public override Java.Lang.Object OnRetainNonConfigurationInstance ()
    {
      base.OnRetainNonConfigurationInstance ();
      return _savedInstance;
    }

    ...

    void PopulateTweetList (string[] results)
    {
      ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results);
      _savedInstance = new TweetListWrapper{Tweets=results};
    }
}

デバイスが回転すると、元の結果が LastNonConfiguartionInstance プロパティから取得されます。 この例では、結果はツイートを含む string[] で構成されています。 OnRetainNonConfigurationInstance では Java.Lang.Object が返される必要があるため、string[]Java.Lang.Object をサブクラス化するクラスにラップされます。このことを次に示します。

class TweetListWrapper : Java.Lang.Object
{
  public string[] Tweets { get; set; }
}

たとえば、次のコードに示すように、OnRetainNonConfigurationInstance から返されるオブジェクトとして TextView を使用しようとすると、アクティビティがリークします。

TextView _textView;

protected override void OnCreate (Bundle bundle)
{
  base.OnCreate (bundle);

  var tv = LastNonConfigurationInstance as TextViewWrapper;

  if(tv != null) {
    _textView = tv;
    var parent = _textView.Parent as FrameLayout;
    parent.RemoveView(_textView);
  } else {
    _textView = new TextView (this);
    _textView.Text = "This will leak.";
  }

  SetContentView (_textView);
}

public override Java.Lang.Object OnRetainNonConfigurationInstance ()
{
  base.OnRetainNonConfigurationInstance ();
  return _textView;
}

このセクションでは、Bundle で単純な状態のデータを保持し、OnRetainNonConfigurationInstance でより複雑なデータ型を保持する方法について説明しました。

まとめ

Android アクティビティ ライフサイクルは、アプリケーション内のアクティビティの状態管理のための強力なフレームワークを提供しますが、理解して実装するのが難しい場合があります。 この章では、アクティビティが有効期間中に通過する可能性があるさまざまな状態と、それらの状態に関連付けられているライフサイクル メソッドについて説明しました。 次に、これらの各メソッドで実行する必要があるロジックの種類に関するガイダンスを提供しました。