获取主线程的消息队列和处理程序

时间:2011-07-02 18:19:23

标签: android message-queue handler looper

如何从另一个线程获取主线程的消息队列? Looper.getMainLooper()获取主线程的looper但我无法找到另一种线程的looper获取MessageQueue的方法。而且,我如何获得主循环器的处理程序?我无法找到任何方法来获得它。

3 个答案:

答案 0 :(得分:3)

@ r.v,

我有类似的需求。我想知道MessageQueue什么时候是空的,当我发布一些东西时,我想知道什么时候它变空了,什么都没做。我查看了MessageQueue.IdleHandler,发现它没有像我想的那样表现出来,我提出了另一个解决方案。

在我的情况下,我想使用Looper / Handler机制来顺序执行文件下载。基本上我想要执行的每个下载都包含在Runnable中。我只希望一次运行一个,所以这种模式运行良好,而不必深入研究更复杂的线程解决方案的细节。另外,我想知道什么时候我第一次把东西放进队列并开始工作,并想知道它什么时候完成(队列是空的)。

我能够使用处理程序的消息机制来实现这一点。消息按Runnables顺序处理,因此您可以策略性地将消息放入队列中,以帮助您了解队列的状况。与Handler队列中的Runnables不同,对于最终提供解决方案的消息,有一些查询和删除功能。

我所做的是每次向Runler添加runnable时(通过Handler.post),我还会删除自定义QUEUE_EMPTY消息的所有实例,然后添加一条新的QUEUE_EMPTY消息。这可以确保我在队列末尾有一条QUEUE_EMPTY消息。一旦我在我的子类处理程序中遇到QUEUE_EMPTY消息,我知道我在队列的末尾。另外,如果我在添加runnable时没有在队列中找到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!");
            }
        }
    }
};

答案 1 :(得分:1)

使用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(...);

现在您可以发送,删除和接收消息。

答案 2 :(得分:0)

在获得主线程looper之后,你应该能够调用myQueue来获取主线程MessageQueue。

http://developer.android.com/reference/android/os/Looper.html#myQueue%28%29