У меня есть рабочий поток, который сидит в фоновом режиме, обрабатывая сообщения. Что-то вроде этого:Как создать поток Looper, а затем отправить ему сообщение немедленно?
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
«s, так как конструктор работает в основном потоке, поэтому Handler
будет ассоциировать себя с неправильным потоком.
Это вряд ли кажется необычным сценарием. Я могу придумать несколько обходных путей, все они некрасиво:
Что-то вроде этого:
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) { // ... } }; notifyAll(); // <- ADDED Looper.loop(); } }
И от основного потока:
Worker worker = new Worker(); worker.start(); worker.wait(); // <- ADDED worker.handler.sendMessage(...);
Но это не является надежным либо : если
notifyAll()
происходит доwait()
, тогда мы никогда не проснемся!Пройдя первоначальный
Message
на конструкторWorker
, имея способrun()
, разместите его. Специальное решение не будет работать для нескольких сообщений, или если мы не хотим сразу его отправлять, но вскоре.Занято-ожидание до
handler
Поле больше неnull
. Да, в крайнем случае ...
Я хотел бы создать Handler
и MessageQueue
от имени Worker
нити, но это не представляется возможным. Каков самый изящный выход из этого?
Любая конкретная причина вы не используете 'HandlerThread'? – CommonsWare
@CommonsWare: Хм, не знал, что он существует. Никаких перекрестных ссылок в документах. Его метод 'getLooper()' блокируется до тех пор, пока у нас не будет 'Looper', тогда мы можем использовать' new Handler (worker.getLooper()) '* из основного потока * для инициализации' Handler'. Это решило бы проблему, верно? – Thomas
думаю. OTOH, я не использую его много, и поэтому я могу что-то упустить. – CommonsWare