web-dev-qa-db-ja.com

HandlerThreadとの通信例

GUIスレッドからHandlerThreadをセットアップしたい。その後しばらくして、GUIでボタンがクリックされると、callHello()が実行され、次に、「Hello World」を非同期に記録する非GUIスレッドにあるHelloLoggerオブジェクトにメッセージが送信されます。私はいくつかのことを試みましたが、いくつかは無期限にブロックし、いくつかはメッセージをまったく受信しませんなどなどです。以下のコードは多かれ少なかれ私が持っているものと同じです。

public class HandlerThreadExample {

    private MyHandlerThread mMyHandlerThread;
    private Looper mLooper;
    private Handler mHandler;

    public HandlerThreadExample(){
        mMyHandlerThread = new MyHandlerThread();
        mMyHandlerThread.start();
        mLooper = mMyHandlerThread.getLooper();
    }
    public void callHello() {
        mHandler.sendEmptyMessage(1);
    }
    private class MyHandlerThread extends HandlerThread {
        private HelloLogger mHelloLogger;
        private Handler mHandler;
        public MyHandlerThread() {
            super("The MyHandlerThread thread", HandlerThread.NORM_PRIORITY);
        }
        public void run (){
            mHelloLogger = new HelloLogger();
            mHandler = new Handler(getLooper()){
                public void handleMessage(Message msg){
                    mHelloLogger.logHello();
                }
            };
            super.run();
        }
    }
    private class HelloLogger {
        public HelloLogger (){
        }
        public void logHello(){
            Log.d("HandlerThreadExample", "Hello World");
        }
    }
}

見つかった最良の例:

少なくとも今、私はいまいましいタブを閉じることができます

pskinkの支援によるソリューション

public class HandlerThreadExample2 {
    private static int MSG_START_HELLO = 0;
    private static int MSG_HELLO_COMPLETE = 1;
    private HandlerThread ht;
    private Handler mHtHandler;
    private Handler mUiHandler;
    private boolean helloReady = false;
    public HandlerThreadExample2(){
        ht = new HandlerThread("The new thread");
        ht.start();
        Log.d(App.TAG, "UI: handler thread started");
        mUiHandler = new Handler(){
            public void handleMessage(Message msg){
                if (msg.what == MSG_HELLO_COMPLETE){
                    Log.d(App.TAG, "UI Thread: received notification of sleep completed ");
                    helloReady = true;              }
            }
        };
        mHtHandler = new Handler(ht.getLooper()){
            public void handleMessage (Message msg){
                if (msg.what == MSG_START_HELLO){
                    Log.d(App.TAG, "handleMessage " + msg.what + " in " + Thread.currentThread() + " now sleeping");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d(App.TAG, "Woke up, notifying UI thread...");
                    mUiHandler.sendEmptyMessage(MSG_HELLO_COMPLETE);
                }
            }
        };
    }
    public void sendLongHello(){
        if (helloReady){
            Log.d(App.TAG, "sending hello " + Thread.currentThread());      
            mHtHandler.sendEmptyMessage(MSG_START_HELLO);
            helloReady = false;
        } else {
            Log.e(App.TAG, "Cannot do hello yet - not ready");
        }
    }
}
29
CL22

これは実際の例です:

HandlerThread ht = new HandlerThread("MySuperAwesomeHandlerThread");
ht.start();
Handler h = new Handler(ht.getLooper()) {
    public void handleMessage(Message msg) {
        Log.d(TAG, "handleMessage " + msg.what + " in " + Thread.currentThread());
    };
};
for (int i = 0; i < 5; i++) {
    Log.d(TAG, "sending " + i + " in " + Thread.currentThread());
    h.sendEmptyMessageDelayed(i, 3000 + i * 1000);
}

[〜#〜] update [〜#〜]

2つのクラスフィールドを作成します。

Handler mHtHandler;
Handler mUiHandler;

これを試してください:

HandlerThread ht = new HandlerThread("MySuperAwsomeHandlerThread");
ht.start();
Callback callback = new Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == 0) {
            Log.d(TAG, "got a meaasage in " + Thread.currentThread() + ", now sleeping... ");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.d(TAG, "woke up, notifying ui thread...");
            mUiHandler.sendEmptyMessage(1);
        } else
        if (msg.what == 1) {
            Log.d(TAG, "got a notification in " + Thread.currentThread());
        }
        return false;
    }
};
mHtHandler = new Handler(ht.getLooper(), callback);
mUiHandler = new Handler(callback);
mHtHandler.sendEmptyMessageDelayed(0, 3000);

もちろん、Callbackインターフェースを削除し、オーバーライドされたhandleMessageメソッドで2つのハンドラーを作成できます...

53
pskink

表示されている問題は、外部クラスがプライベートmHandlerフィールドを使用しているため、HandlerThreadも使用しているためです。外部クラスのフィールドは初期化されていません。内側のmHandlerは必要ありません。外部クラスは、start()を呼び出した直後に取得したルーパーからハンドラーを作成できます。

1
Larry Schiefer