Nat*_*ate 1 android handler executor looper
我正在使用Executor [固定线程池]和我自己的ThreadFactory添加一个Looper:
Handler HANDLER = new Handler();
Executor THREADS = Executors.newFixedThreadPool(THREAD_POOL_SIZE, new ThreadFactory() {
@Override public Thread newThread(Runnable runnable) {
return new MyThread(new Runnable() {
@Override public void run() {
Looper.prepare();
runnable.run();
}
});
}
});
private static class MyHandler extends Handler {
public boolean fail;
public void handleMessage(Message msg) {
switch(msg.what) {
case 1:
this.fail = msg.arg1 == 1;
Looper.myLooper().quit();
break;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我正在运行一个发出网络请求的线程,但如果网络出现故障,我希望向用户显示一条对话框消息.这个过程非常复杂,因为它需要在UI线程中进行AND显示请求.我可以通过简单地向网络线程添加一个循环并等待从UI线程发送消息来等待用户对该对话框的响应.这允许我在一段时间(tryAgain)线程中封装网络请求.一切正常,除非第二次调用Looper.loop()方法(显示第二个网络错误对话框后),并且对话框(在UI线程中)将消息发送到网络线程的处理程序:
THREADS.execute(new Runnable() {
private MyHandler myHandler = new MyHandler();
@Override public void run() {
boolean tryAgain = true;
while(tryAgain) {
try {
switch(request) {
[Handle network requests]
}
tryAgain = false;
} catch(IOException e) {
// The network is unavailable. Ask the user if we should try again.
e.printStackTrace();
} finally {
if(tryAgain) {
HANDLER.post(new Runnable() { // The UI thread
@Override public void run() {
theAlertDialog.show();
}
});
// Wait for the results from the dialog which lives in the UI thread.
Looper.loop();
// At this point the dialog has informed us of our answer.
tryAgain = !myHandler.fail;
}
}
}
}
});
Run Code Online (Sandbox Code Playgroud)
在AlertDialog实例中是一个OnClickListener:
DialogInterface.OnClickListener myOnclickListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Message msg = myHandler.obtainMessage(1);
msg.setTarget(this.handler);
msg.sendToTarget();
}
}
Run Code Online (Sandbox Code Playgroud)
我已经检查过线程仍然处于活动状态,handler.getLooper().getThread().isAlive()它总是返回true,但它仍然让我"在死线程上向处理程序发送消息".消息/处理程序如何确定线程已死?它不应该依赖于.isAlive()方法吗?最后我试图避免将线程管理构建复制到Android操作系统中:-)
如果你检查android/os/MessageQueue.java中的源代码,你可以看到如下内容
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
}
Run Code Online (Sandbox Code Playgroud)
因此,在第一次调用Looper.quit()之后,消息队列基本上无法使用,因为它将具有空目标的消息排入队列,这是消息队列停止排队并显示为"死"的神奇标识符.
| 归档时间: |
|
| 查看次数: |
6142 次 |
| 最近记录: |