父活动未从线程接收消息

时间:2013-09-06 16:55:10

标签: android multithreading

我的测试应用程序大致基于Cristian Baita的threads tutorial。 它按预期工作,但是从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);

然后应该通过MainActivity中定义的mainHandler接收消息:

    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从不记录“已接收消息”或“已处理消息...”。所以消息永远不会到达它的目的地。

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;
}

}

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

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

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

在我关注的示例代码中,Cristian Baita在@Override方法之前没有使用handleMessage()语句。这是公平的,因为@Override只是方便您和您的编译器突出显示错误。令人尴尬的是,我认为因为@Override不在那里,我们并没有凌驾于其中。希望这个滑动可以帮助其他人学习他们的学习曲线。

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