请考虑以下代码段:
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()之前进行回调;消息会排队还是丢失?处理程序将runnable发布到原始线程,回调到这个线程。
答案 0 :(得分: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;
}
}
我假设你的线程池是一个MyThread线程池,每个线程都有自己的Looper。线程池应该初始化你的线程,所以一旦你交付了一个由你的线程执行的Runnable,run()方法应该初始化Looper。
另一方面,如果你想将你的Handler与一个特定的looper相关联(即你没有在上面这样的线程中构造Handler),那么你应该将Looper线程传递给构造函数,如:
Handler h = new Handler(myLooperThread);
如果你没有指定,那么处理程序使用创建它的线程从ThreadLocal对象中获取该线程的Looper。
最后,如果您的意图是在与UI线程关联的Handler上传递消息,那么您不应该担心调用Looper.prepare或Looper.loop。这由活动处理。