【问题标题】:What happens if a Handler posts a message to a thread after Looper.prepare() but before Looper.loop() has been called?如果 Handler 在 Looper.prepare() 之后但在 Looper.loop() 被调用之前向线程发送消息会发生什么?
【发布时间】:2015-03-10 01:00:55
【问题描述】:

考虑以下 sn-p:

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

一点背景知识:我正在 UI 线程上进行一些处理,我需要 ping 大量设备并对结果进行处理。我需要并行执行请求以提高效率。

问题:如果其中一个用例以某种方式执行得足够快并在我能够点击 Looper.loop() 之前进行了回调;消息会排队还是丢失?回调正在通过将可运行对象发布到原始线程的处理程序发送回此线程。

【问题讨论】:

    标签: android looper


    【解决方案1】:

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

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

    看着sn-p,我不太确定事情是如何联系在一起的。 通常你想像这样构造一个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;
        }
    }
    

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

    另一方面,如果您希望将您的 Handler 与特定的 looper 相关联(即,您没有像上面那样在线程中构造 Handler),那么您应该将 Looper 线程传递给构造函数,如下所示:

    Handler h = new Handler(myLooperThread);
    

    如果您不指定,则处理程序使用创建它的线程从 ThreadLocal 对象中获取该线程的 Looper。

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

    【讨论】:

    • 所以,基本上在他的sn-p处理消息上MessageQueue会延迟for循环的执行时间。
    • 差不多。任何传递给未初始化 Looper 的尝试都将导致运行时异常。根据需要,IntentService 可能是更好的选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    相关资源
    最近更新 更多