How do I get the message queue of the main thread from another thread? Looper.getMainLooper() gets the main thread's looper but I am unable to find a way to get the MessageQueue for another thread's looper. Moreover, how do I get the handler for the main looper? I am unable to find any way to get it.
3 に答える
@rv、
私にも同様のニーズがありました。MessageQueue がいつ空になるか、いつ何かを投稿するかを知りたいと思っていました。を調べたところ、MessageQueue.IdleHandler
意図したとおりに動作しないことがわかりました。別の解決策を思いつきました。
私の場合、ルーパー/ハンドラー メカニズムを使用して、ファイルのダウンロードを順次実行したいと考えていました。基本的に、実行したい各ダウンロードは Runnable にラップされています。一度に 1 つだけ実行したいので、このパターンは、より複雑なスレッド ソリューションのナットとボルトを掘り下げる必要なくうまく機能します。さらに、最初に何かをキューに入れ、その作業が開始されたのはいつなのか、いつ完全に完了したのか (キューが空になったのか) を知りたいと思っていました。
これを実現するために、ハンドラーのメッセージ メカニズムを使用することができました。メッセージは Runnables で順番に処理されるため、戦略的にメッセージをキューに配置して、キューの状態を知ることができます。ハンドラーのキュー内の Runnables とは異なり、最終的に解決策を提供するメッセージのクエリおよび削除機能がいくつかあります。
私がやっていることは、(経由で)ランナブルをハンドラに追加するたびにHandler.post
、カスタムメッセージのすべてのインスタンスも削除してからQUEUE_EMPTY
、新しいQUEUE_EMPTY
メッセージを追加することです。これによりQUEUE_EMPTY
、キューの最後にメッセージがあることが保証されます。サブクラス化された Handler でメッセージに遭遇するQUEUE_EMPTY
と、キューの最後にいることがわかります。QUEUE_EMPTY
さらに、ランナブルを追加するときにキューにメッセージが見つからない場合は、キューが空で、スレッドがアイドル状態だったことがわかります。
一部の人がすぐに指摘するように、このソリューションには実際に非効率な点がいくつかあります。キューに多数のエントリがある場合、これらの「マーカー」メッセージのキューを反復処理する必要があると、実際のパフォーマンスの問題になる可能性があります。私の場合、一度に処理するファイルのダウンロードはほんの一握りなので、パフォーマンスの低下は無視できます。同様の状況にある場合、これはかなり合理的な解決策だと思います。Android SDK がこれらの基本的な機能をMessageQueue
. 理想的には、MessageQueue をいじりたくないことに同意しますが、アイドル状態/動作中/空であることを知ることは合理的なことのように思えます。これらのことを知る価値があるシナリオはたくさんあると確信しています。
class DownloaderThread extends Thread
{
private static final int QUEUE_EMPTY = 9999;
private MyHandler handler;
@Override
public void run()
{
try
{
Looper.prepare();
handler = new MyHandler();
Looper.loop();
}
catch (Throwable t)
{
Log.e(TAG, "halted due to an error", t);
}
}
public void post(Runnable r)
{
if(!handler.hasMessages(QUEUE_EMPTY))
{
Log.v(TAG, "Download queue was empty. First element being added.");
}
handler.post(r);
handler.removeMessages(QUEUE_EMPTY);
handler.sendEmptyMessage(QUEUE_EMPTY);
}
class MyHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
if(msg.what == QUEUE_EMPTY)
{
Log.v(TAG, "Download runnable queue is empty!");
}
}
}
};
メインスレッドルーパーを取得したら、myQueueを呼び出してメインスレッドMessageQueueを取得できるようになります。
http://developer.android.com/reference/android/os/Looper.html#myQueue%28%29
Handler クラスを使用して、ルーパーのメッセージ キューと対話します。
メインスレッドのメッセージ キューを操作するには、
Handler mainHandler = new Handler(Looper.getMainLooper(), new Callback() {
@Override
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
return false;
}
});
mainHandler.post(...);
mainHandler.sendMessage(...);
mainHandler.removeMessage(...);
メッセージの送信、削除、受信ができるようになりました。