1

我正在尝试创建一个简单的多人游戏。有一个WorkerService应该处理所有网络通信,并且此服务与我的活动之间的所有交互都是使用 AIDL 完成的。我认为这是一种标准方法——为了实现双向交互,我还使用了一个IWorkerCallback接口(也是 AIDL)。

问题是回调必须改变 UI 中的东西,这可能只能在 UI 线程中完成。我创建了一个Handler(在 UI 线程中)并相信这是一个明显的解决方案。但是,令人惊讶的是,它不起作用。

我的接口LoungeActivity调用startServer()方法。IWorker我的相应方法WorkerService做了一些工作并进行了回调 - 这很好用。然后WorkerService产生一个新线程并从该线程回调导致抛出一个错误的异常:

Can't create handler inside thread that has not called Looper.prepare()

这里有一些代码可以清楚地说明:

startServer()执行:

private void startServerImpl(String name, float latStart, float latEnd,
float lonStart, float lonEnd)
{
    // some instructions here

    // this works fine:
    callback.notifySocketCreated();

    // my naughty thread:
    new ServerThread().start();

    // some instructions here
}

ServerThread代码:

private class ServerThread extends Thread {
    @Override
    public void run()
    {
        //some instructions here

        // this call will cause an error
        callback.notifyGameRegistered();

    }
}

每个方法callback看起来都是这样的:

public void notifyGameRegistered() throws RemoteException
{
    handler.dispatchMessage(handler.obtainMessage(CALLBACK_GAME_REGISTERED));
}

在处理程序的handleMessage()方法中,我正在做一个简单的switch(msg.what),并且在每种情况下都有一个简单的 UI 修改(显示 Toast,更改文本等)。

我不知道为什么会抛出这个异常。我已经设法通过将代码打包到 aRunnable并调用来修复它,runOnUiThread()但它仍然让我很好奇 - 处理程序不应该总是在创建它的线程中运行吗?或者也许我做错了什么?

4

3 回答 3

1

我知道这有点晚了——但问题是你打电话来了dispatchMessage()

正确的方法是sendMessage()

dispatchMessage()将调用handleMessage()同一个线程。

我猜问题不是你的处理程序在错误的线程上——而是用户界面试图在你的 onHandle() 方法的某个地方创建一个处理程序。因为在错误的线程上调用了 onHandle(),所以你得到了一个异常。

/**
 * Handle system messages here.
 */
public void dispatchMessage(Message msg)
{
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        handleMessage(msg);
    }
}
于 2011-07-06T04:56:37.577 回答
0

您必须以某种方式从主线程调用有问题的函数。

于 2010-05-04T22:26:20.370 回答
0

更改 UI 的函数应该在拥有 UI 的 Activity 中。

这个链接应该可以帮助你: http ://android-developers.blogspot.com/2009/05/painless-threading.html

于 2010-10-01T19:29:47.080 回答