如果Handler在Looper.prepare()之后但在调用Looper.loop()之前将消息发布到线程会发生什么?

Cha*_*had 12 android looper

请考虑以下代码段:

Looper.prepare();
handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            getLooper().quitSafely();
        }
    };
for(int i = 0; i < urls.size(); i++) {
    useCaseProvider.get().execute(callback, handler, urls.get(i), threadPool);
}
Looper.loop();

//Continue processing the results of all the use cases after the    
//loop has been asked to terminated via the handler
Run Code Online (Sandbox Code Playgroud)

一点背景:我正在对UI线程进行一些处理,我需要ping一大堆设备并对结果做一些事情.我需要并行执行请求才能高效.

问题:如果其中一个用例以某种方式执行得足够快并在我能够命中Looper.loop()之前进行了回调; 消息会排队还是丢失?处理程序将runnable发布到原始线程,回调函数将被回发到此线程.

jag*_*und 7

假设您在useCaseProvider交付结果之前调用了Looper.prepare(),那么您应该没问题.如果没有调用Looper.prepare,你应该看到抛出RuntimeException.

Looper对象绑定到托管消息队列的本地线程.Looper.prepare函数将构造此消息队列,此时您可以开始对消息进行排队.一旦你触发Looper.loop(),就会开始执行那些待处理的消息.

看看片段,我不太确定事情是如何捆绑在一起的.通常你想构造一个像这样的looper:

private static final class MyThread extends Thread {
    private Handler mHandler;

    @Override
    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // handle message
            }
        };

        Looper.loop();
    }

    public Handler getHandler() {
        return mHandler;
    }
}
Run Code Online (Sandbox Code Playgroud)

我假设您的线程池是一个MyThread线程池,每个线程都有自己的Looper.线程池应该初始化你的线程,所以一旦你交付了一个由你的线程执行的Runnable,run()方法应该初始化Looper.

另一方面,如果您希望将Handler与特定的循环器关联(即,您没有在上面的线程中构建Handler),那么您应该将Looper线程传递给构造函数,如:

Handler h = new Handler(myLooperThread);
Run Code Online (Sandbox Code Playgroud)

如果没有指定,那么处理程序使用创建它的线程从ThreadLocal对象中获取该线程的Looper.

最后,如果您的意图是在与UI线程关联的Handler上传递消息,那么您不应该担心调用Looper.prepare或Looper.loop.这由Activity处理.