Я пытаюсь создать простую многопользовательскую игру. Существует WorkerService
, который должен обрабатывать все сетевые коммуникации и все взаимодействие между этой службой и моей деятельностью осуществляется с помощью AIDL. Я думаю, что это стандартный подход - для обеспечения двустороннего взаимодействия я использую также интерфейс IWorkerCallback
(также AIDL).
Проблема в том, что обратные вызовы должны изменить вещи в пользовательском интерфейсе, что может быть сделано только в потоке пользовательского интерфейса. Я создал Handler
(в потоке пользовательского интерфейса) и считаю, что это очевидное решение. Но, что удивительно, это не работает.
Мой 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)
, и в каждом случае есть простая модификация пользовательского интерфейса (показ тоста, изменение текста и т. Д.).
Понятия не имею, почему выбрасывается это исключение. Мне удалось исправить его, упаковав код в Runnable
и вызвав runOnUiThread()
, но это все равно вызывает у меня любопытство - не должен ли обработчик всегда работать в потоке что создал это? А может я что-то не так делаю?