У мене є робоча нитка, яка сидить у фоновому режимі і обробляє повідомлення. Щось на зразок цього:
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?