@ r.v
У меня была похожая потребность. Я хотел знать, когда 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!");
}
}
}
};