У меня есть рабочий поток, который находится в фоновом режиме и обрабатывает сообщения. Примерно так:
class Worker extends Thread {
public volatile Handler handler; // actually private, of course
public void run() {
Looper.prepare();
mHandler = new Handler() { // the Handler hooks up to the current Thread
public boolean handleMessage(Message msg) {
// ...
}
};
Looper.loop();
}
}
Из основного потока (потока пользовательского интерфейса, не то чтобы это важно) я хотел бы сделать что-то вроде этого:
Worker worker = new Worker();
worker.start();
worker.handler.sendMessage(...);
Проблема в том, что это настраивает меня на красивое состояние гонки: в то время worker.handler
, невозможно быть уверенным, что рабочий поток уже назначен этому полю!
Я не могу просто создать обработчик Handler
из Worker
, потому что конструктор работает в основном потоке, поэтому обработчик
ассоциирует себя с неправильным потоком.
Это вряд ли кажется необычным сценарием. Я могу придумать несколько обходных путей, и все они ужасны: публичный обработчик volatile Handler; // на самом деле частный, конечно public void run () { Looper.prepare (); mHandler = new Handler () {// Обработчик подключается к текущему потоку public boolean handleMessage (сообщение сообщение) { // ... } }; notifyAll (); // <- ДОБАВЛЕНО Looper.loop (); } }
И из основного потока:
Worker worker = new Worker ();
worker.start ();
worker.wait (); // <- ДОБАВЛЕНО
worker.handler.sendMessage (...);
Но это тоже ненадежно: если notifyAll ()
произойдет до wait ()
, то нас никогда не разбудят!
Передача начального Сообщение
конструктору Worker
, отправив его методом run ()
. Специальное решение не будет работать для нескольких сообщений, или если мы не хотим отправлять его сразу, но вскоре после этого.
Занят-ожидание, пока поле обработчика
больше не будет ноль
. Да, в крайнем случае ...
Я хотел бы создать Handler
и MessageQueue
от имени потока Worker
, но это не похоже быть возможным. Каков самый элегантный выход из этого?