6

異なるスレッドから同じルーパーをリッスンするハンドラーを実装しようとしています。

以下に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 }

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

4

2 に答える 2

12

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

は、送信されたメッセージ/実行可能ファイルが実行されるスレッドLooperを示します。コードでは、別々のスレッドで作成されているにもかかわらず、両方のハンドラーがメインスレッドで実行されます。これが、インスタンスを...に渡すことができる本当の理由です。noを渡すと、は、インスタンス作成されたスレッド(スレッドでもある必要があります)でコードを実行します。handleMessage()LooperHandlerLooperHandlerLooper

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

于 2013-03-21T02:31:00.690 に答える
1

に送信されたメッセージは、それがを共有している場合でも、それHandlerによってのみ処理されます。HandlerLooper

Handlerのソースコードに埋め込まれているのは次の行です

msg.target = this;

これにより、他の人がそれHandlerに触れることがなくなります。

于 2013-03-21T02:16:16.950 に答える