他のスレッドからGUIを更新するには、基本的に2つの主要なアプローチがあります。
次のいずれかの方法でJava.lang.Runnableを使用します。
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
Handler.post(Runnable)
Android.os.Messageを使用します。
Handler.sendMessage(Message) / Handler.handleMessage(Message)
AsyncTaskを使用することもできますが、私の質問は、非常に単純なコンポーネントを更新するユースケースに焦点を当てています。両方のアプローチを使用してどのように行われるかを見てみましょう。
Runnablesの使用:
TextViev tv = ...;
final String data = "hello";
Runnable r = new Runnable() {
@Override
public void run(){
tv.setText(data);
}
};
//Now call Activity.runOnUiThread(r) or handler.post(r), ...
メッセージの使用:
Message m = handler.obtainMessage(UPDATE_TEXT_VIEW, "hello");
handler.sendMessage(m);
//Now on handler implementation:
@Override
public void handleMessage(Message msg) {
if(msg.what == UPDATE_TEXT_VIEW){
String s = (String) msg.obj;
tv.setText(data);
} ... //other IFs?
}
私見、メッセージは行く方法ではありません:理由:
一方、Runnablesは、よく知られているコマンドパターンに従い、プログラマーにとって使いやすく、読みやすくなっています。
では、RunnableよりもMessagesを使用する利点は何ですか?現代のメッセージはバックグラウンドにプッシュされていますかAndroidプログラミング?Runnablesでは実行できないメッセージで実行できることはありますか?
前もって感謝します。
Message
とRunnable
の使用にはほとんど違いがないと思います。それは主に個人的な好みに要約されます。どうして?ソースコードを見ると、Runnable
の投稿はまったく同じメッセージングメカニズムを使用していることがわかります。 Runnable
をMessage
にアタッチし、それを送信するだけです。
4.4.2ソースコード
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
参照: Grepコード-ハンドラー
Messages
は再利用できるため、作成されるオブジェクトとGCが少なくなります。また、クラスと匿名タイプが少なくなります。
大きな利点の1つは、Message
をHandler
に送信するクラスがそのMessage
の実装について何も知る必要がないことです。これは、使用場所によってはカプセル化に役立ちます。
最後に、間の清浄度の違いを検討してください
_mHandler.obtainMessage(DO_STUFF, foo).sendToTarget();
_
vs
_final Foo tempFoo = foo;
mHandler.post(new Runnable(){
@Override
public void run(){
doStuff(tempFoo);
}
};
_
doStuff()
が必要な場所が複数ある場合、前者の方がはるかに読みやすく、コードの重複が少なくなります。
ドキュメントによると、Handler
インターフェースはrunOnUiThread()
よりもはるかに多くの機能を提供します。
ハンドラーの主な用途は2つあります。
(1)メッセージとランナブルを将来のある時点で実行するようにスケジュールする
(2)自分のスレッドとは異なるスレッドで実行されるアクションをキューに入れます。
runOnUiThread
は(2)のサブセットのみを実行します。つまり、「実行するアクションをキューに入れてUIスレッド "
したがって、これらの追加機能が必要でない限り、IMOはrunOnUiThread
で十分で好ましい方法です。
Runnable
よりもMessage
の方が好きです。イベント処理コードはイベントに非常に近いため、Runnable
を使用するコードはMessage
よりもはるかに明確だと思います。また、定数とスイッチケースを定義するオーバーヘッドを回避できます。
そして、Runnable
の使用がカプセル化に違反するとは思いません。 Runnable.run()
のコードを外部クラスの別のメソッド(たとえばon...Event()
)に抽出したり、EventHandler
オブジェクトにラップしたりすることもできます。どちらの方法も、Message
を使用するよりもはるかに明確です。特に、Message
にストア参照が必要な場合は、Runnable
を使用するとmsg.obj
のダウンキャストが回避されるためです。また、名前のないフィールドmsg.obj
もエラーが発生しやすく、理解するのが非効率的である場合があります。
また、Runnable
は、フィールドとして保存することで再利用することもできます。