1

我下面的测试应用程序大致基于 Cristian Baita 的这个线程教程。它按预期工作,但从 myThread 的 run() 方法发送的消息从未被 MainActivity 的处理程序接收到。

我将 MainActivity 的处理程序传递给线程构造函数中的 myThread。然后我使用该处理程序的 sendMessage() 方法将消息发送回 MainActivity,但处理程序似乎从未收到它。为什么是这样?

注意:我发现在 Eclipse 中使用断点进行调试对线程来说是一件痛苦的事情,所以我最终使用 Log 语句而不是帮助跟踪应用程序的执行。

我已将完整的代码放在这篇文章的末尾,但总结一下:

MyThread 类的构造函数从调用活动中获取处理程序,如下所示。

public class MyThread extends Thread {

    // Reference to mainHandler from the mainThread
    private Handler parentHandler;

    // Constructor
    public MyThread(Handler pHandler) {
        parentHandler = pHandler;
    }

当我在 MainActivity 的 onCreate() 方法中创建线程时,我将它传递给处理程序mainHandler

myThread = new MyThread(mainHandler);
myThread.start();

然后在 MyThread 的 run() 方法中,我有:

    Message messageToParent = Message.obtain();
    messageToParent.what = 2;
    Log.i("myThread", "About to send message to parent ...");
    parentHandler.sendMessage(messageToParent);

然后应该通过mainHandlerMainActivity 中定义的方式接收消息:

    public Handler mainHandler = new Handler() {
        public void handleMessages(Message msg){
            Log.i("MainActivity", "Message Received");
            switch(msg.what) {
                case 2:
                    Log.i("MainActivity", "Handled message. msg.what = " + msg.what);
    ....

如果您在运行时观察 LogCat 窗口,您将看到 MainActivity 从未记录“收到的消息”或“已处理的消息...”。所以消息永远不会到达它的目的地。

主要活动:

public class MainActivity extends Activity {

private MyThread myThread;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    myThread = new MyThread(mainHandler);
    myThread.start();

    // Message the thread
    Message msgToThread = Message.obtain();
    msgToThread.what = 4;
    Log.i("MainActivity", "About to send message to thread...");
    myThread.getHandler().sendMessage(msgToThread);
}

public Handler mainHandler = new Handler() {
    public void handleMessages(Message msg){
        Log.i("MainActivity", "Message Received");
        switch(msg.what) {
            case 2:
                Log.i("MainActivity", "Handled message. msg.what = " + msg.what);

                // Message the thread
                Message msgToThread = Message.obtain();
                msgToThread.what = 6;
                myThread.getHandler().sendMessage(msgToThread);

                break;
            default:
                Log.i("MainActivity", "Unhandled message. msg.what = " + msg.what);
                break;
        }
    }
};
}

MyThread 类:

public class MyThread extends Thread {

// Reference to mainHandler from the mainThread
private Handler parentHandler;

// Constructor
public MyThread(Handler pHandler) {
    parentHandler = pHandler;
}

// Local handler for messages to this thread
private Handler myThreadHandler = new Handler() {
    public void handleMessage(Message msg) {

        switch(msg.what) {

            case 4:
                Log.i("myThread", "Handled message. msg.what = " + msg.what);
                break;

            case 6:
                Log.i("myThread", "Handled message. msg.what = " + msg.what);
                break;

            default:
                Log.i("myThread", "Unhandled message. msg.what = " + msg.what);
                break;              
        }
    }
};


@Override
public void run() {     
    super.run();

    int count = 0;
    boolean keepGoing = true;

    try {

        while(true) {

            Log.i("myThread", "run() method - while loop is ticking ..." + count);

            // some arbitrary conditions to make stuff happen
            switch(count) {
                case 5:
                    Message messageToParent = Message.obtain();
                    messageToParent.what = 2;
                    Log.i("myThread", "About to send message to parent ...");
                    parentHandler.sendMessage(messageToParent);
                    break;
                case 10:
                    keepGoing = false;
                    break;
            }

            if(!keepGoing) {
                Log.i("myThread", "myThread is going to stop");
                break;
            }

            count++;
            sleep(500);

        }

    } 
    catch (Exception e) {
        Log.e("My Log", "Thread Loop Exception - " + e);
    }
    Log.i("myThread", "myThread has reached the end of it's run() method");
}

public Handler getHandler() {
    return myThreadHandler;
}

}
4

2 回答 2

0

乍一看,这可能是因为您的父处理程序是私有的。将其更改为公开并尝试一次!

于 2013-09-07T05:08:00.607 回答
0

handleMessage()当我们为处理程序编写方法时,我意识到我误解了我们正在做的事情。

我以为我们正在为处理程序编写一个新方法,所以我将它命名为稍微不同handleMessages()的名称(注意复数)。

事实上,我们正在做的是覆盖处理程序的现有方法之一。

在我遵循的示例代码中,Cristian Baita 没有在他的方法@Override之前使用语句。handleMessage()这很公平,因为@Override只是为了方便您和您的编译器突出错误。令人尴尬的是,我的错是假设因为@Override不存在,所以我们没有覆盖任何东西。希望这个失误能帮助其他一些人在他们的学习曲线上。

顺便说一句:我仍然会彻底推荐 Cristian Baita 的 3 线程教程,因为它们解释得非常清楚且易于理解。问题是我的,在做出假设!

于 2013-09-07T07:42:41.327 回答