I'm trying to create a simple multiplayer game. There's a WorkerService
which is supposed to handle all network communication and all interaction between this service and my Activities is done with AIDL. I think this is a standard approach - to enable two way interaction I use also an IWorkerCallback
interface (also AIDL).
The problem is that callbacks have to change things in UI which may be done only in UI thread. I've created a Handler
(in UI thread) and believed that this is an obvious solution. But, surprisingly, it's not working.
My LoungeActivity
calls startServer()
method of IWorker
interface. Corresponding method of my WorkerService
does some job and makes a callback - this works fine. Then WorkerService
spawns a new thread and callback from this thread results in a bad Exception being thrown:
Can't create handler inside thread that has not called Looper.prepare()
Here's some code to make it clear:
startServer()
implementation:
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
code:
private class ServerThread extends Thread {
@Override
public void run()
{
//some instructions here
// this call will cause an error
callback.notifyGameRegistered();
}
}
Every method from callback
looks like that:
public void notifyGameRegistered() throws RemoteException
{
handler.dispatchMessage(handler.obtainMessage(CALLBACK_GAME_REGISTERED));
}
In Handler's handleMessage()
method I'm doing a simple switch(msg.what)
and in every case there's a simple UI modification (showing a Toast, changing Text, etc.).
I have no idea why is this Exception thrown.. I've managed to fix it by packing code into a Runnable
and calling runOnUiThread()
but it still makes me curious - shouldn't a Handler always run in thread that created it? Or maybe I'm doing something wrong?