Handlers と runOnUiThread の両方の概念に出会いました。しかし、私にとっては、どの事実に基づいてそれらが正確に異なるのか、まだ疑問のようです。
どちらも、バックグラウンドスレッドからUIアクションを実行することを目的としています。しかし、2つの方法から選択する際に考慮すべき要因は何ですか。
たとえば、バックグラウンドでWebサービスを実行するRunnable
Thread
を考えてみましょう。ここでUIを更新します。
UIを更新する最良の方法は何ですか? Handler
またはrunOnUiThread
に行くべきですか?
AsyncTask
を使用してonPostExecute
を使用できることはまだわかっています。しかし、違いを知りたいだけです。
Activity.runOnUiThread() は、より一般的な特殊なケースです Handlers 。 Handler
を使用すると、独自のスレッド内で独自のイベントクエリを作成できます。 デフォルトコンストラクターでインスタンス化されたHandlers
を使用すると、does n'tは "code一般的にUIスレッドで実行されます」。デフォルトでは、ハンドラーはインスタンス化元のThread
にバインドされます。
UI(メイン)スレッドへのバインドが保証されるHandler
を作成するには、Main LooperにバインドされたHandler
オブジェクトを作成する必要がありますこの:
_Handler mHandler = new Handler(Looper.getMainLooper());
_
さらに、runOnUiThread()
メソッドの実装を確認する場合、Handler
を使用して次のことを行います。
_ public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
_
上記のコードスニペットからわかるように、runOnUiThread()
がUIスレッドから呼び出されると、_Runnable action
_がすぐに実行されます。それ以外の場合は、Handler
にポストします。これは、後のある時点で実行されます。
ハンドラーには、メッセージパッシングなどの多くの作業があり、タスクを実行するためにスレッドを開始すると頻繁にUIが更新されます。スレッドのMessageQueueに関連付けられた実行可能なオブジェクト。これは、Bluetoothチャット、Wi-Fiチャットなどの多くのアプリケーションで非常に便利です。
あなたはこれを見なければなりません
http://developer.Android.com/guide/components/processes-and-threads.html
http://developer.Android.com/tools/testing/activity_testing.html
HitOdessitの回答に続きます。
このようなクラスを作成できます。
public class Global{
private static Handler mHandler = new Handler(Looper.getMainLooper());
public static void runOnUiThread(Runnable action){
mHandler.post(action);
}
}
そして、このように呼び出します。
Global.runOnUiThread(new Runnable(){
//Your code
});
そして、これはどこからでも実行できます(グローバルクラスにアクセスできる場所)。
ハンドラーは古い方法(APIレベル1)で、AsycTask
(APIレベル1)の使用に重点を置いて、runOnUIThread
(APIレベル3)が導入されました。ハンドラーの使用はできるだけ避け、必要に応じて他の2つを選択する必要があります。
UIを更新する最良の方法は何ですか? HandlerまたはrunOnUiThreadに行くべきですか?
Runnable
でUIを更新する必要がある場合は、runOnUiThread
に投稿してください。
ただし、UIスレッドにRunnable
を常に投稿できるとは限りません。
ネットワーク/ IO操作またはWebサービスを呼び出す必要があるシナリオを考えてください。この場合、Runnable
をUIスレッドに投稿できません。 Android.os.NetworkOnMainThreadException
をスローします
これらのタイプのRunnable
は、 HandlerThread のような異なるスレッドで実行する必要があります。操作の完了後、UIスレッドに関連付けられているHandler
を使用して、結果をUIスレッドにポストバックできます。
public void onClick(View view) {
// onClick on some UI control, perform Network or IO operation
/* Create HandlerThread to run Network or IO operations */
HandlerThread handlerThread = new HandlerThread("NetworkOperation");
handlerThread.start();
/* Create a Handler for HandlerThread to post Runnable object */
Handler requestHandler = new Handler(handlerThread.getLooper());
/* Create one Handler on UI Thread to process message posted by different thread */
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Runnable on HandlerThread is completed and got result:"+(String)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
NetworkRunnable r1 = new NetworkRunnable("http://www.google.com/",responseHandler);
NetworkRunnable r2 = new NetworkRunnable("http://in.rediff.com/",responseHandler);
requestHandler.post(r1);
requestHandler.post(r2);
}
class NetworkRunnable implements Runnable{
String url;
Handler uiHandler;
public NetworkRunnable(String url,Handler uiHandler){
this.url = url;
this.uiHandler=uiHandler;
}
public void run(){
try {
Log.d("Runnable", "Before IO call");
URL page = new URL(url);
StringBuffer text = new StringBuffer();
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
BufferedReader buff = new BufferedReader(in);
String line;
while ((line = buff.readLine()) != null) {
text.append(line + "\n");
}
Log.d("Runnable", "After IO call:"+ text.toString());
Message msg = new Message();
msg.obj = text.toString();
/* Send result back to UI Thread Handler */
uiHandler.sendMessage(msg);
} catch (Exception err) {
err.printStackTrace();
}
}
}