Androidスレッドモデル
6456 ワード
Androidのスレッドモデル
この記事では、Androidアプリケーションで使用されるスレッドモデルについて説明し、メインスレッドではなく作業者スレッドを作成することによって時間のかかる操作を処理するアプリケーションの最適なUIレンダリングを確保する方法について説明します.この記事では、メインスレッドで実行されるUIコンポーネントとインタラクティブなAPI、および管理対象ワーカースレッドを作成するAPIについても説明します.
UIスレッド
アプリケーションが起動すると、mainというスレッドが作成されます.UIスレッドとも呼ばれるプライマリ・スレッドは、ペイント・イベントを含むコンポーネントへのイベントの配布を担当するため、非常に重要です.このスレッドでもあり、ここでAndroid UIツールパッケージのコンポーネントとインタラクティブになります.
例えば、画面上のボタンをタッチすると、UIスレッドはタッチイベントをコンポーネントに配布し、コンポーネントは自分が押された状態に設定し、無効な要求をイベントキューに投げ出す.UIスレッドキューは、コンポーネントに自分の描画を要求し、通知する.
プログラムがうまく実現しない限り、単一スレッドモデルはパフォーマンスを低下させます.特に、すべての操作が単一のスレッドで行われると、ネットワークアクセス、データ照会などの時間のかかる操作がUIをブロックする.時間のかかる操作を実行すると、ペイントされたイベントを含むイベントは配布されません.ユーザーの視覚から見ると、アプリケーションがハングアップされています.さらに悪いことに、UIスレッドのブロックが一定時間(現在は約5秒)を超えると、システムはユーザーに悪い「アプリケーション応答なし」(ANR)ダイアログボックスを表示します.
これがどれほど悪いかを見たいなら、ButtonのOnClickListener関数でThreadを呼び出す簡単なアプリケーションを書くことができます.sleep(2000).ボタンは通常の状態に戻るまで2秒間押し続けます.このような状況が発生すると、ユーザーはアプリケーションが遅いと考えやすい.
要するに、アプリケーションUIの応答性にとって、UIスレッドがブロックされないことを保証することが重要である.時間のかかる操作がある場合は、別のスレッド(バックグラウンドまたはワーカースレッド)で実行することを確認する必要があります.
次の例では、イベント処理関数をクリックして、ネットワークから画像をダウンロードし、ImageViewに表示します.
一見、UIスレッドをブロックしないため、このコードはあなたの問題をよく解決することができます.残念なことに、UIの単一スレッドモデルに反しています.Android UIツールパッケージはスレッドが安全ではなく、UIスレッドで操作する必要があります.上記のコードクリップでは、ImageViewはワーカースレッドで動作するため、撮影可能な問題が発生します.これらのBugの追跡と修正は困難で時間がかかる可能性があります.
Androidは、他のスレッドでUIスレッドにアクセスできる方法を提供しています.いくつかはよく知っているかもしれませんが、ここは比較的包括的なリストです.
· Activity.runOnUiThread(Runnable)
· View.post(Runnable)
· View.postDelayed(Runnable, long)
· Handler
これらのクラスとメソッドのいずれかを使用して、上記の例のコードを修正できます.
残念なことに、これらのクラスと方法は、コードをより複雑にし、読みにくくする可能性があります.特に、複雑な操作を実現する場合、UIを頻繁に更新する必要があります.
この問題を解決するために、Android 1.5とその後のプラットフォームは、長い時間タスクを実行する作成プロセスを簡素化し、UIとインタラクティブにする汎用クラスAsyncTaskを提供しています.
Android 1.0や1.1には、AsyncTaskに似たものもあり、UserTaskと呼ばれています.同じAPIを提供していますが、コードをコピーする必要があります.
AsyncTaskの目的は、スレッドの管理を支援することです.私たちの前の例はAsyncTaskで簡単に書き換えることができます.
ご覧のように、AsyncTaskは使用を継承しなければなりません.さらに、AsyncTaskのインスタンスはUIスレッドで作成され、一度しか実行できないことも覚えておいてください.AsyncTaskのドキュメントを読むと、使用方法を完全に理解できますが、ここでは、その作業手順とその作業手順を簡単に説明します.
・汎用型を使用してパラメータ、進捗値、最終結果のタイプを指定できます
・doInBackground()メソッド自動ワーカースレッドで実行
・onPreExecute()onPostExecute()およびonProgressUpdate()がメインスレッドで呼び出される
・doInBackground()で返される値はonPostExecute()メソッドに送信される
・doInBackground()でpublishProgress()をいつでも呼び出してonProgressUpdate()を実行できます
・任意のスレッドからタスクをいつでもキャンセルできます
公式のドキュメントに加えて、Shelves(ShelvesActivity.javaおよびAddBookActivity.java)やPhotostream(LoginActivity,PhotostreamActivity.java、ViewPhotoActivity.javaなどの複雑な例のソースコードも参照できます.Shelvesのソースコードを読んで、構成変更時のタスクの保存とActivityの破棄時にタスクを正しくキャンセルする方法を強くお勧めします.
AsyncTaskを使用するかどうかにかかわらず、単一スレッドモデルでは常に2つの法則を覚えておく必要があります.
1.UIスレッドをブロックしない
2.UIスレッドでのみAndroid UIキットにアクセスできることを確認
この記事では、Androidアプリケーションで使用されるスレッドモデルについて説明し、メインスレッドではなく作業者スレッドを作成することによって時間のかかる操作を処理するアプリケーションの最適なUIレンダリングを確保する方法について説明します.この記事では、メインスレッドで実行されるUIコンポーネントとインタラクティブなAPI、および管理対象ワーカースレッドを作成するAPIについても説明します.
UIスレッド
アプリケーションが起動すると、mainというスレッドが作成されます.UIスレッドとも呼ばれるプライマリ・スレッドは、ペイント・イベントを含むコンポーネントへのイベントの配布を担当するため、非常に重要です.このスレッドでもあり、ここでAndroid UIツールパッケージのコンポーネントとインタラクティブになります.
例えば、画面上のボタンをタッチすると、UIスレッドはタッチイベントをコンポーネントに配布し、コンポーネントは自分が押された状態に設定し、無効な要求をイベントキューに投げ出す.UIスレッドキューは、コンポーネントに自分の描画を要求し、通知する.
プログラムがうまく実現しない限り、単一スレッドモデルはパフォーマンスを低下させます.特に、すべての操作が単一のスレッドで行われると、ネットワークアクセス、データ照会などの時間のかかる操作がUIをブロックする.時間のかかる操作を実行すると、ペイントされたイベントを含むイベントは配布されません.ユーザーの視覚から見ると、アプリケーションがハングアップされています.さらに悪いことに、UIスレッドのブロックが一定時間(現在は約5秒)を超えると、システムはユーザーに悪い「アプリケーション応答なし」(ANR)ダイアログボックスを表示します.
これがどれほど悪いかを見たいなら、ButtonのOnClickListener関数でThreadを呼び出す簡単なアプリケーションを書くことができます.sleep(2000).ボタンは通常の状態に戻るまで2秒間押し続けます.このような状況が発生すると、ユーザーはアプリケーションが遅いと考えやすい.
要するに、アプリケーションUIの応答性にとって、UIスレッドがブロックされないことを保証することが重要である.時間のかかる操作がある場合は、別のスレッド(バックグラウンドまたはワーカースレッド)で実行することを確認する必要があります.
次の例では、イベント処理関数をクリックして、ネットワークから画像をダウンロードし、ImageViewに表示します.
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap(b);
}
}).start();
}
一見、UIスレッドをブロックしないため、このコードはあなたの問題をよく解決することができます.残念なことに、UIの単一スレッドモデルに反しています.Android UIツールパッケージはスレッドが安全ではなく、UIスレッドで操作する必要があります.上記のコードクリップでは、ImageViewはワーカースレッドで動作するため、撮影可能な問題が発生します.これらのBugの追跡と修正は困難で時間がかかる可能性があります.
Androidは、他のスレッドでUIスレッドにアクセスできる方法を提供しています.いくつかはよく知っているかもしれませんが、ここは比較的包括的なリストです.
· Activity.runOnUiThread(Runnable)
· View.post(Runnable)
· View.postDelayed(Runnable, long)
· Handler
これらのクラスとメソッドのいずれかを使用して、上記の例のコードを修正できます.
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(b);
}
});
}
}).start();
}
残念なことに、これらのクラスと方法は、コードをより複雑にし、読みにくくする可能性があります.特に、複雑な操作を実現する場合、UIを頻繁に更新する必要があります.
この問題を解決するために、Android 1.5とその後のプラットフォームは、長い時間タスクを実行する作成プロセスを簡素化し、UIとインタラクティブにする汎用クラスAsyncTaskを提供しています.
Android 1.0や1.1には、AsyncTaskに似たものもあり、UserTaskと呼ばれています.同じAPIを提供していますが、コードをコピーする必要があります.
AsyncTaskの目的は、スレッドの管理を支援することです.私たちの前の例はAsyncTaskで簡単に書き換えることができます.
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
ご覧のように、AsyncTaskは使用を継承しなければなりません.さらに、AsyncTaskのインスタンスはUIスレッドで作成され、一度しか実行できないことも覚えておいてください.AsyncTaskのドキュメントを読むと、使用方法を完全に理解できますが、ここでは、その作業手順とその作業手順を簡単に説明します.
・汎用型を使用してパラメータ、進捗値、最終結果のタイプを指定できます
・doInBackground()メソッド自動ワーカースレッドで実行
・onPreExecute()onPostExecute()およびonProgressUpdate()がメインスレッドで呼び出される
・doInBackground()で返される値はonPostExecute()メソッドに送信される
・doInBackground()でpublishProgress()をいつでも呼び出してonProgressUpdate()を実行できます
・任意のスレッドからタスクをいつでもキャンセルできます
公式のドキュメントに加えて、Shelves(ShelvesActivity.javaおよびAddBookActivity.java)やPhotostream(LoginActivity,PhotostreamActivity.java、ViewPhotoActivity.javaなどの複雑な例のソースコードも参照できます.Shelvesのソースコードを読んで、構成変更時のタスクの保存とActivityの破棄時にタスクを正しくキャンセルする方法を強くお勧めします.
AsyncTaskを使用するかどうかにかかわらず、単一スレッドモデルでは常に2つの法則を覚えておく必要があります.
1.UIスレッドをブロックしない
2.UIスレッドでのみAndroid UIキットにアクセスできることを確認