アクティビティは Android アプリケーションの基本的な構成要素であり、さまざまな状態に存在できます。 アクティビティのライフサイクルはインスタンス化から始まり、破棄で終わり、その間に多くの状態が含まれます。 アクティビティが状態を変更すると、適切なライフサイクル イベント メソッドが呼び出され、近い状態の変化をアクティビティに通知し、その変更に適応するコードを実行できるようになります。 この記事では、アクティビティのライフサイクルを調べ、これらの状態の各変更中にアクティビティが適切に動作し、信頼性の高いアプリケーションの一部になる責任について説明します。
アクティビティ ライフサイクルの概要
アクティビティは、Android に固有の通常とは異なるプログラミング概念です。 従来のアプリケーション開発では、通常、アプリケーションを起動するために実行される静的 main メソッドがあります。 しかし、Androidでは、物事は異なります。Android アプリケーションは、アプリケーション内で登録されている任意のアクティビティを介して起動できます。 実際には、ほとんどのアプリケーションには、アプリケーション エントリ ポイントとして指定された特定のアクティビティのみが含まれます。 ただし、アプリケーションがクラッシュした場合、または OS によって終了された場合、OS は最後に開いているアクティビティまたは前のアクティビティ スタック内の任意の場所でアプリケーションの再起動を試みることができます。 さらに、OS はアクティブでないときにアクティビティを一時停止し、メモリが不足している場合は再利用することがあります。 特にそのアクティビティが以前のアクティビティのデータに依存している場合は、アクティビティが再起動された場合にアプリケーションがその状態を正しく復元できるように注意深く検討する必要があります。
アクティビティのライフサイクルは、アクティビティのライフサイクル全体にわたって OS が呼び出すメソッドのコレクションとして実装されます。 これらのメソッドを使用すると、開発者はアプリケーションの状態とリソース管理の要件を満たすために必要な機能を実装できます。
アプリケーション開発者は、各アクティビティの要件を分析して、アクティビティ ライフサイクルによって公開されるメソッドを実装する必要があるかどうかを判断することが非常に重要です。 これを行わないと、アプリケーションが不安定になり、クラッシュし、リソースが肥大化し、場合によっては基になる OS が不安定になる可能性があります。
この章では、以下を含むアクティビティのライフサイクルについて詳しく説明します。
- アクティビティの状態
- ライフサイクル メソッド
- アプリケーションの状態の保持
このセクションには、アクティビティのライフサイクル中に状態を効率的に保存する方法に関する実用的な例を示す チュートリアル も含まれています。 この章の終わりまでに、アクティビティのライフサイクルと、Android アプリケーションでアクティビティをサポートする方法を理解している必要があります。
アクティビティのライフサイクル
Android アクティビティライフサイクルは、開発者にリソース管理フレームワークを提供する Activity クラス内で公開されるメソッドのコレクションで構成されます。 このフレームワークを使用すると、開発者はアプリケーション内の各アクティビティの固有の状態管理要件を満たし、リソース管理を適切に処理できます。
アクティビティの状態
Android OS は、その状態に基づいてアクティビティを裁定します。 これにより、Android は、使用されなくなったアクティビティを識別し、OS がメモリとリソースを再利用できるようにします。 次の図は、アクティビティが有効期間中に通過できる状態を示しています。
これらの状態は、次のように 4 つの主要なグループに分割できます。
アクティブまたは実行中 – アクティビティは、アクティビティ スタックの最上位とも呼ばれるフォアグラウンドにある場合、アクティブまたは実行中と見なされます。 これは Android で最も優先度の高いアクティビティと見なされるため、アクティビティがデバイスで使用できるメモリを超えるメモリを使用しようとする場合など、極端な状況では OS によってのみ強制終了されます。これにより、UI が応答しなくなる可能性があります。
一時停止 – デバイスがスリープ状態になった場合、またはアクティビティがまだ表示されているが、フル サイズではない、または透過的な新しいアクティビティによって部分的に非表示になっている場合、アクティビティは一時停止と見なされます。 一時停止されたアクティビティは引き続き有効です。つまり、すべての状態とメンバー情報が維持され、ウィンドウ マネージャーにアタッチされたままです。 これは Android で 2 番目に優先度の高いアクティビティと見なされます。そのため、このアクティビティを強制終了すると、アクティブ/実行中アクティビティの安定性と応答性を維持するために必要なリソース要件を満たす場合にのみ、OS によって強制終了されます。
停止/バックグラウンド – 別のアクティビティによって完全に隠されたアクティビティは、停止またはバックグラウンドと見なされます。 停止されたアクティビティは、状態とメンバーの情報をできるだけ長く保持しようとしますが、停止されたアクティビティは 3 つの状態の中で最も優先度が低いと見なされ、そのため、OS は優先順位の高いアクティビティのリソース要件を満たすために、最初にこの状態のアクティビティを強制終了します。
再起動 – ライフサイクルで一時停止から停止までの任意の場所にあるアクティビティを Android によってメモリから削除できます。 ユーザーがアクティビティに戻った場合は、再起動し、以前に保存した状態に復元してから、ユーザーに表示する必要があります。
構成の変更に対応するアクティビティ Re-Creation
さらに複雑にするために、Androidは構成変更と呼ばれるミックスにもう1つのレンチを投げます。 構成の変更は、アクティビティの構成が変更されたときに発生する迅速なアクティビティの破棄/再作成サイクルです。たとえば、デバイスが 回転したとき (また、アクティビティを横モードまたは縦モードで再組み込む必要がある場合)、キーボードが表示されたとき (およびアクティビティにサイズを変更する機会が表示される)、またはデバイスがドックに配置されたときなどです。 特に、
構成の変更により、アクティビティの停止と再起動中に発生するのと同じアクティビティ状態の変更が引き続き発生します。 ただし、アプリケーションが応答性を感じ、構成の変更中に適切に実行されるようにするには、できるだけ早く処理することが重要です。 このため、Android には、構成の変更中に状態を保持するために使用できる特定の API があります。 これについては、後の「 ライフサイクル全体の状態の管理」セクションで 説明します。
アクティビティ ライフサイクル メソッド
Android SDK と、さらに Xamarin.Android フレームワークは、アプリケーション内のアクティビティの状態を管理するための強力なモデルを提供します。 アクティビティの状態が変化すると、アクティビティは OS によって通知され、そのアクティビティに対して特定のメソッドが呼び出されます。 次の図は、アクティビティ ライフサイクルに関連するこれらのメソッドを示しています。
開発者は、アクティビティ内でこれらのメソッドをオーバーライドすることで、状態の変更を処理できます。 ただし、すべてのライフサイクル メソッドが UI スレッドで呼び出され、現在のアクティビティの非表示、新しいアクティビティの表示など、OS による次の UI 作業の実行がブロックされることに注意することが重要です。そのため、アプリケーションのパフォーマンスを高めるために、これらのメソッドのコードはできるだけ短くする必要があります。 実行時間の長いタスクは、バックグラウンド スレッドで実行する必要があります。
これらの各ライフサイクル メソッドとその使用方法を調べてみましょう。
OnCreate
OnCreate は、アクティビティの作成時に呼び出される最初のメソッドです。
OnCreate は、次のようなアクティビティで必要になる可能性があるスタートアップ初期化を実行するために常にオーバーライドされます。
- ビューを作成する
- 変数の初期化
- 静的データをリストにバインドする
OnCreate は Bundle パラメーターを受け取ります。これは、アクティビティ間で状態情報とオブジェクトを格納および渡すためのディクショナリです。バンドルが 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
}
}
OnResumeOnPauseで行われる操作は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 つあります。
OnResumeは、アクティビティがフォアグラウンドに返される場合に呼び出されます。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されます。
戻るとホーム
多くの Android デバイスには、"戻る" ボタンと "ホーム" ボタンの 2 つの異なるボタンがあります。 この例は、Android 4.0.3 の次のスクリーンショットで確認できます。
2 つのボタンは、アプリケーションをバックグラウンドに配置する場合と同じ効果を持っているように見えますが、微妙な違いがあります。 ユーザーが [戻る] ボタンをクリックすると、アクティビティが完了したことを Android に通知します。 Android はアクティビティを破棄します。 これに対し、ユーザーが [ホーム] ボタンをクリックすると、アクティビティは単にバックグラウンドに配置されます。Android はアクティビティを強制終了しません。
ライフサイクル全体の状態の管理
アクティビティが停止または破棄されると、システムは後でリハイドレートするためにアクティビティの状態を保存する機会を提供します。 この保存された状態は、インスタンス状態と呼ばれます。 Android には、アクティビティのライフサイクル中にインスタンスの状態を格納するための 3 つのオプションが用意されています。
Android が状態の保存に使用するバンドルと呼ばれる
Dictionaryにプリミティブ値を格納する。ビットマップなどの複雑な値を保持するカスタム クラスを作成する。 Android では、このカスタム クラスを使用して状態を保存します。
構成変更ライフサイクルを回避し、アクティビティの状態を維持するための完全な責任を想定します。
このガイドでは、最初の 2 つのオプションについて説明します。
バンドルの状態
インスタンスの状態を保存するための主なオプションは、バンドルと呼ばれるキー/値ディクショナリ オブジェクトを使用 することです。
OnCreate メソッドがパラメーターとしてバンドルを渡すアクティビティが作成されると、このバンドルを使用してインスタンスの状態を復元できることを思い出してください。 キーと値のペア (ビットマップなど) にすばやくまたは簡単にシリアル化できない、より複雑なデータにバンドルを使用することはお勧めしません。むしろ、文字列のような単純な値に使用する必要があります。
Activity には、バンドル内のインスタンス状態の保存と取得に役立つメソッドが用意されています。
OnSaveInstanceState – これは、アクティビティが破棄されるときに Android によって呼び出されます。 アクティビティは、キー/値の状態項目を保持する必要がある場合に、このメソッドを実装できます。
OnRestoreInstanceState – これは、
OnCreateメソッドの完了後に呼び出され、初期化が完了した後にアクティビティが状態を復元する別の機会を提供します。
次の図は、これらのメソッドの使用方法を示しています。
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で表示します。 次の図に示すように、構成の変更が発生した場合 (たとえば、デバイスが回転した場合) は、bundleがnullされるため、上記のコードはcの値を失います。
この例の c の値を保持するために、アクティビティは OnSaveInstanceStateをオーバーライドし、次に示すように値をバンドルに保存します。
protected override void OnSaveInstanceState (Bundle outState)
{
outState.PutInt ("counter", c);
base.OnSaveInstanceState (outState);
}
デバイスが新しい向きに回転されると、整数がバンドルに保存され、行と共に取得されます。
c = bundle.GetInt ("counter", -1);
注
ビュー階層の状態を保存できるように、常に OnSaveInstanceState の基本実装を呼び出す必要があります。
ビューの状態
OnSaveInstanceStateのオーバーライドは、上の例のカウンターなど、向きの変化にまたがってアクティビティに一時的なデータを保存するための適切なメカニズムです。 ただし、 OnSaveInstanceState の既定の実装では、各ビューに ID が割り当てられている限り、すべてのビューの UI に一時的なデータを保存する処理が行われます。 たとえば、アプリケーションに XML で次のように定義された EditText 要素があるとします。
<EditText android:id="@+id/myText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
EditText コントロールにはidが割り当てられているため、ユーザーがデータを入力してデバイスを回転させると、次に示すようにデータが表示されます。
OnRestoreInstanceState
OnRestoreInstanceState は、 OnStart後に呼び出されます。 以前のOnSaveInstanceState中にバンドルに保存された状態を復元する機会をアクティビティに提供します。 ただし、これは OnCreateに提供されるバンドルと同じです。
次のコードは、 OnRestoreInstanceStateで状態を復元する方法を示しています。
protected override void OnRestoreInstanceState(Bundle savedState)
{
base.OnRestoreInstanceState(savedState);
var myString = savedState.GetString("myString");
var myBool = savedState.GetBoolean("myBool");
}
このメソッドは、状態を復元する必要がある場合の柔軟性を提供するために存在します。 インスタンスの状態を復元する前に、すべての初期化が完了するまで待つ方が適切な場合があります。 さらに、既存のアクティビティのサブクラスは、インスタンスの状態から特定の値のみを復元したい場合があります。 ほとんどのアクティビティは、OnCreateに提供されたバンドルを使用して状態を復元できるため、多くの場合、OnRestoreInstanceStateをオーバーライドする必要はありません。
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);
}
}
このコードは、次のスクリーンショットに示すように、JSON 形式の Web から結果を取得し、解析してから、結果を一覧に表示します。
構成の変更が発生した場合 (たとえば、デバイスのローテーション時など)、コードはプロセスを繰り返します。 最初に取得した結果を再利用し、不要で冗長なネットワーク呼び出しを引き起こさないように、次に示すように、 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 アクティビティライフサイクルは、アプリケーション内のアクティビティの状態管理のための強力なフレームワークを提供しますが、理解して実装するのは難しい場合があります。 この章では、アクティビティが有効期間中に通過する可能性があるさまざまな状態と、それらの状態に関連付けられているライフサイクル メソッドについて説明しました。 次に、これらの各メソッドで実行する必要があるロジックの種類に関するガイダンスを提供しました。


![[戻る] ボタンと [ホーム] ボタン](images/image4-sml.png)



