2013-03-21 12 views
5

ハンドラが異なるスレッドから同じLooperでリッスンするよう実装しようとしています。Looper.getMainLooper()で初期化されたハンドラがメッセージコールバックに応答しない

以下に、2つのハンドラがあります.1つはメインスレッドで作成され、もう1つは子スレッドで作成されますが、どちらもメインルーパーでリッスンするように初期化されます。

private Handler mMain; 
public static final ThreadPoolExecutor tpe = 
     (ThreadPoolExecutor) Executors.newCachedThreadPool(); 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    mMain = new Handler(Looper.getMainLooper()) { 
     @Override 
     public void handleMessage(Message msg) { 
      Log.wtf("", "main:" + msg); 
     } 
    }; 

    tpe.execute(new Runnable() { 
     private Handler tChild = new Handler(Looper.getMainLooper()) { 
      @Override 
      public void handleMessage(Message msg) { 
       Log.wtf("", "child:" + msg); 
      } 
     }; 

     @Override 
     public void run() { 
      Log.wtf("", "send msg to main looper"); 
      tChild.sendEmptyMessage(100); 
     } 
    }); 
} 

しかし、以下のようなメッセージを送信すると、子ハンドラだけがメッセージを出力します。メインハンドラはメッセージを受信しません。

03-20 22:02:26.754: A/(12857): send msg to main looper 
03-20 22:02:26.847: A/(12857): child:{ what=100 when=-8ms } 

私は間違っていますか?読んでくれてありがとう。

答えて

10

Handlerのインスタンスはのターゲットを制御するため、共有する方法はありません。したがって、Handlerに送信されるすべてのメッセージまたは投稿はそのインスタンスによってのみ実行されます。

Looperは、のメッセージが送信されるスレッドを実行すると、を示します。あなたのコードでは、両方のハンドラは別のスレッドで作成されているにもかかわらず、メインスレッドでhandleMessage()を実行します。あなたは何Looperに合格しない場合には、... あなたはHandlerLooperインスタンスを渡すことができる本当の理由で、その後Handlerは(もLooperスレッドもその必見)が作成されたスレッド上でコードを実行します。

このため、このようにデータを送信する複数のハンドラを作成する理由はありません。単一のHandlerは、複数のスレッドからメッセージを送信するように設計されており、すべてMessageQueueでシリアル化され、選択されたLooperスレッドで実行されます。バックグラウンドスレッドから直接mMainに投稿して、そのスレッドのコードを実行することができます。この場合、Looperを渡すことは、コードがすでにメインスレッド上にある場合は冗長です。

+0

私は、ありがとう!ある日、Runnableが内部クラスではなく外部クラスだったとすると、私は初期化されたHandlerをそのコンストラクタ経由で渡すべきでしょうか? –

+0

アーキテクチャはアプリケーションに依存しますが、メッセージを投稿する予定がある場合は、どこからでも 'Handler'への参照が必要になります。 – Devunwired

+0

アプリケーションコンテキスト(アプリケーションを拡張するクラス)でHandler(this.getMainLooper())を1つだけ使用するのはなぜですか?これをアクティビティで行うよりもきれいではないでしょうか? –

1

Handlerに送信されたメッセージは、Looperを共有していても、Handlerによってのみ処理されます。

ハンドラのソースコードに埋もれ

msg.target = this; 

ラインであるこれは、他のHandlerがそれを触れないことが保証されます。

関連する問題