简体   繁体   English

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

[英]What happens if a Handler posts a message to a thread after Looper.prepare() but before Looper.loop() has been called?

Consider the following snippet: 请考虑以下代码段:

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

A little background: I'm doing some processing on the UI thread where I will need to ping a large about of devices and do something with the result. 一点背景:我正在对UI线程进行一些处理,我需要ping一大堆设备并对结果做一些事情。 I need to perform the requests in parallel to be efficient. 我需要并行执行请求才能高效。

Question: If one of these use cases somehow executed fast enough and made a callback before I was able to hit Looper.loop(); 问题:如果其中一个用例以某种方式执行得足够快并在我能够命中Looper.loop()之前进行了回调; would the message be queued or just lost? 消息会排队还是丢失? Callbacks are being posted back to this thread by the handler posting a runnable to the original thread. 处理程序将runnable发布到原始线程,回调函数将被回发到此线程。

Assuming you have invoked Looper.prepare() prior to your useCaseProvider delivering results, you should be fine. 假设您在useCaseProvider交付结果之前调用了Looper.prepare(),那么您应该没问题。 If Looper.prepare was not called you should be seeing RuntimeException being thrown. 如果没有调用Looper.prepare,你应该看到抛出RuntimeException。

The Looper object is tied to a thread local which hosts the message queue. Looper对象绑定到托管消息队列的本地线程。 The Looper.prepare function will construct this message queue at which point you can begin queuing up messages. Looper.prepare函数将构造此消息队列,此时您可以开始排队消息。 Once you fire Looper.loop() that's when those pending messages will begin to execute. 一旦你触发Looper.loop(),就会开始执行那些待处理的消息。

Looking at the snippet, I'm not too sure how things are tied together. 看看片段,我不太确定事情是如何捆绑在一起的。 Generally you want to construct a looper like this: 通常你想构造一个像这样的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;
    }
}

I'm assuming your thread pool is then a pool of MyThread threads, each of which have their own Looper. 我假设您的线程池是一个MyThread线程池,每个线程都有自己的Looper。 The thread pool should initialize your threads so once you deliver a Runnable to be executed by your thread, the run() method should have the Looper initialized. 线程池应该初始化你的线程,所以一旦你交付了一个由你的线程执行的Runnable,run()方法应该初始化Looper。

On the other hand, if you wish to associate your Handler with a particular looper (ie. you are not constructing the Handler within a thread like above) then you should be passing the Looper thread in to the constructor like: 另一方面,如果您希望将Handler与特定的循环器关联(即,您没有在上面的线程中构建Handler),那么您应该将Looper线程传递给构造函数,如:

Handler h = new Handler(myLooperThread);

If you don't specify that, then the handler uses the thread in which it was created to grab that thread's Looper from the ThreadLocal object. 如果没有指定,那么处理程序使用创建它的线程从ThreadLocal对象中获取该线程的Looper。

Lastly if your intentions are to have messages delivered on the Handler which is associated with the UI thread then you should not be concerned about calling Looper.prepare or Looper.loop. 最后,如果您的意图是在与UI线程关联的Handler上传递消息,那么您不应该担心调用Looper.prepare或Looper.loop。 This is handled by the Activity. 这由Activity处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法在尚未调用looper.prepare的线程内创建处理程序 - cant create handler inside thread that has not called looper.prepare 无法在未调用looper.prepare()的线程内创建处理程序 - cannot create handler inside thread that has not called looper.prepare() 无法在未调用Looper.prepare()的线程内创建处理程序 - Can not create handler inside thread that has not called Looper.prepare() 无法在未调用Looper.prepare()Android的线程内创建处理程序。 循环计时器 - Can't create handler inside thread that has not called Looper.prepare() Android. Loop in a timer 发出Toast消息时出错:无法在未调用Looper.prepare()的线程内创建处理程序 - Error while dispaying an Toast message: Can't create handler inside thread that has not called Looper.prepare() android中主UI线程的Looper.prepare()和Looper.loop()方法调用 - Method call for Looper.prepare() and Looper.loop() for main UI thread in android 无法在Handler()内未调用Looper.prepare()的线程内创建处理程序 - Can't create handler inside thread that has not called Looper.prepare() inside Handler() Android处理程序:无法在尚未调用Looper.prepare()的线程内创建处理程序 - Android handler: Can't create handler inside thread that has not called Looper.prepare() Handler或runOnUiThread解决方案“无法在未调用Looper.prepare()的线程内创建处理程序” - Handler or runOnUiThread solution for “Can't create handler inside thread that has not called Looper.prepare() ” Android线程错误-无法在未调用Looper.prepare()的线程内创建处理程序 - Android thread error - Can't create handler inside thread that has not called Looper.prepare()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM