J'essaie de créer un jeu multijoueur simple. Il y a un WorkerService
qui est censé gérer toutes les communications réseau et toutes les interactions entre ce service et mes activités se font avec AIDL. Je pense que c'est une approche standard - pour permettre une interaction bidirectionnelle, j'utilise aussi une interface IWorkerCallback
(aussi AIDL).Le rappel d'un autre thread provoque une exception
Le problème est que les rappels doivent changer les choses dans l'interface utilisateur, ce qui peut être fait uniquement dans le thread de l'interface utilisateur. J'ai créé un Handler
(dans le fil de l'interface utilisateur) et je crois que c'est une solution évidente. Mais, étonnamment, ça ne marche pas.
Mes LoungeActivity
appels startServer()
méthode de IWorker
interface. La méthode correspondante de mon WorkerService
fait du travail et fait un rappel - cela fonctionne bien. Puis WorkerService
fraie un nouveau thread et le rappel de ce fil entraîne une mauvaise exception levée:
Can't create handler inside thread that has not called Looper.prepare()
est ici un code pour préciser:
startServer()
mise en œuvre:
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();
}
}
Chaque méthode de callback
ressemble que:
public void notifyGameRegistered() throws RemoteException
{
handler.dispatchMessage(handler.obtainMessage(CALLBACK_GAME_REGISTERED));
}
Dans la méthode de gestionnaire handleMessage()
que je fais simple switch(msg.what)
et dans tous les cas il y a une modification de l'interface utilisateur simple (montrant une modification du texte, Toast, etc.). Je n'ai aucune idée de pourquoi cette Exception est levée .. J'ai réussi à la corriger en plaçant le code dans un Runnable
et en appelant runOnUiThread()
mais cela me rend toujours curieux - un gestionnaire ne devrait-il pas toujours fonctionner dans le thread qui l'a créé? ? Ou peut-être que je fais quelque chose de mal?
Eh bien .. Je le fais maintenant. Mais pourquoi handleMessage est-il exécuté dans deux threads différents?Une fois qu'il est dans l'interface utilisateur (notifySocketCreated()) et une autre fois pas (notifyGameRegistered()). – omarcin