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");
}
}
}
これは実際の例です:
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つのハンドラーを作成できます...
表示されている問題は、外部クラスがプライベートmHandlerフィールドを使用しているため、HandlerThreadも使用しているためです。外部クラスのフィールドは初期化されていません。内側のmHandlerは必要ありません。外部クラスは、start()を呼び出した直後に取得したルーパーからハンドラーを作成できます。