Пример взаимодействия с HandlerThread
Я хочу настроить HandlerThread из потока графического интерфейса. Затем, спустя некоторое время, когда нажата кнопка в GUI, она запускает callHello(), которая затем отправляет сообщение в объект HelloLogger, находящийся в потоке без GUI, который асинхронно регистрирует "Hello World". Я пробовал несколько вещей, некоторые блоки на неопределенный срок, некоторые никогда не получают сообщение и т.д. И т.д. Кодекс ниже более или менее близок к тому, который у меня есть, пожалуйста, может ли кто-нибудь изменить его на работу?
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");
}
}
}
Ответы
Ответ 1
Это рабочий пример:
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
Сделайте два поля класса:
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().