Получить очередь сообщений основного обработчика и обработчик

Как мне получить очередь сообщений основного потока из другого потока? 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(...);

Теперь вы можете отправлять, удалять и получать сообщения.

Другие вопросы по тегам