1

我正在使用带有我自己的 ThreadFactory 的 Executor [固定线程池],它添加了一个 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;
            }
        }
    }
}

我正在运行一个发出网络请求的线程,但如果网络出现故障,我希望向用户显示一条对话框消息。这个过程相当复杂,因为它需要在 UI 线程中发出并显示请求。我可以通过简单地向网络线程添加一个循环并等待从 UI 线程发送消息来等待用户对对话框的响应。这允许我将网络请求封装在一个 while(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;
                }
            }
        }
    }
});

在 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();
    }
}

我已经检查过该线程仍然处于活动状态,handler.getLooper().getThread().isAlive()它总是返回 true,但它仍然给我“向死线程上的处理程序发送消息”。消息/处理程序如何决定线程已死?它不应该依赖 .isAlive() 方法吗?最后,我试图避免将线程管理构建复制到 Android 操作系统中:-)

4

2 回答 2

6

如果您检查 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;
            }
   }

所以在第一次调用 Looper.quit() 之后消息队列基本上是不可用的,因为它会将具有空目标的 Message 入队,这是消息队列停止入队并出现“死”的神奇标识符。

于 2010-11-23T10:16:34.393 回答
1

请参阅http://code.google.com/p/android/issues/detail?id=20915,这可能是问题的根本原因。它包括该问题的解决方法。

于 2011-10-18T21:08:07.590 回答