Получить очередь сообщений основного обработчика и обработчик
Как мне получить очередь сообщений основного потока из другого потока? Looper.getMainLooper() получает петлитель основного потока, но я не могу найти способ получить MessageQueue для петлителя другого потока. Кроме того, как мне получить обработчик для основного петлителя? Я не могу найти способ получить это.
3 ответа
@rv,
У меня была похожая потребность. Я хотел знать, когда MessageQueue пуст и когда я публикую что-то для этого, и я хочу знать, когда он станет пустым, и ничего не останется. Я посмотрел на MessageQueue.IdleHandler
и обнаружил, что он не ведет себя так, как я хотел, я нашел другое решение.
В моем случае я хотел использовать механизм Looper/Handler для последовательного выполнения загрузки файлов. В основном каждая загрузка, которую я хочу выполнить, оборачивается в Runnable. Я хочу, чтобы работал только по одному, поэтому этот шаблон работает хорошо, без необходимости углубляться в гайки и болты более сложного резьбового раствора. Кроме того, я хотел знать, когда я впервые помещаю что-то в очередь, и она начинает свою работу, и хотел знать, когда это будет полностью сделано (очередь пуста).
Я смог использовать механизм сообщений обработчика для достижения этой цели. Сообщения обрабатываются последовательно с помощью Runnables, поэтому вы можете стратегически размещать сообщения в очереди, чтобы помочь вам узнать условия очереди. В отличие от Runnables в очереди обработчика, существуют некоторые возможности запросов и удаления для сообщений, которые в конечном итоге обеспечивают решение.
То, что я делаю, это каждый раз, когда я добавляю работающий объект в обработчик (через Handler.post
) Я также удаляю все экземпляры кастома QUEUE_EMPTY
сообщение, а затем добавить свежий QUEUE_EMPTY
сообщение. Это гарантирует, что у меня есть QUEUE_EMPTY
сообщение в конце очереди. Однажды я столкнулся с QUEUE_EMPTY
сообщение в моем обработчике подкласса, я знаю, что я в конце очереди. Кроме того, если я не найду QUEUE_EMPTY
Сообщение в очереди, когда я иду, чтобы добавить исполняемый файл, я знаю, что очередь была пуста, и поток был свободен.
Как быстро скажут некоторые, в этом решении есть некоторые реальные недостатки. Необходимость итерации по очереди для этих "маркерных" сообщений может быть реальной проблемой производительности, если в очереди имеется большое количество записей. В моем случае я имею дело только с несколькими загрузками файлов за раз, поэтому любые потери производительности незначительны. Если у вас похожая ситуация, думаю, это довольно разумное решение. Было бы неплохо, чтобы Android SDK предоставил эти основные возможности MessageQueue
, Я согласен, что в идеале вы не захотите связываться с MessageQueue, но знание того, когда оно бездействует / работает / пусто, кажется разумным, и я уверен, что существует множество сценариев, когда есть смысл знать эти вещи.
class DownloaderThread extends Thread
{
private static final int QUEUE_EMPTY = 9999;
private MyHandler handler;
@Override
public void run()
{
try
{
Looper.prepare();
handler = new MyHandler();
Looper.loop();
}
catch (Throwable t)
{
Log.e(TAG, "halted due to an error", t);
}
}
public void post(Runnable r)
{
if(!handler.hasMessages(QUEUE_EMPTY))
{
Log.v(TAG, "Download queue was empty. First element being added.");
}
handler.post(r);
handler.removeMessages(QUEUE_EMPTY);
handler.sendEmptyMessage(QUEUE_EMPTY);
}
class MyHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
if(msg.what == QUEUE_EMPTY)
{
Log.v(TAG, "Download runnable queue is empty!");
}
}
}
};
После того, как вы получите петли основных потоков, вы сможете просто вызвать myQueue, чтобы получить основные потоки MessageQueue.
http://developer.android.com/reference/android/os/Looper.html
Используйте класс Handler для взаимодействия с очередью сообщений Looper.
Чтобы взаимодействовать с очередью сообщений основного потока,
Handler mainHandler = new Handler(Looper.getMainLooper(), new Callback() {
@Override
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
return false;
}
});
mainHandler.post(...);
mainHandler.sendMessage(...);
mainHandler.removeMessage(...);
Теперь вы можете отправлять, удалять и получать сообщения.