У мене є робоча нитка, яка сидить у фоновому режимі і обробляє повідомлення. Щось на зразок цього:
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
'', тому що конструктор працює на основному потоці, тому файл 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
конструктору «S, що маєrun()
метод пост він. Спеціальне рішення не працюватиме для кількох повідомлень або якщо ми не хочемо надсилати його відразу, але незабаром після цього.Зайнятий очікуванням, поки
handler
поля більше не будеnull
. Так, крайній засіб ...
Я хотів би створити Handler
і MessageQueue
від імені Worker
потоку, але, схоже, це неможливо. Який найелегантніший вихід із цього?
HandlerThread
?