Simple BusProvider.getInstance().post()
amène l'exception non main thread
. Comment envoyer un événement du service à l'activité avec le bus d'événements Otto?
Pour publier à partir de n'importe quel fil (principal ou en arrière-plan) et recevoir sur le fil principal, essayez quelque chose comme
public class MainThreadBus extends Bus {
private final Handler mHandler = new Handler(Looper.getMainLooper());
@Override
public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
} else {
mHandler.post(new Runnable() {
@Override
public void run() {
MainThreadBus.super.post(event);
}
});
}
}
}
Remarque: le mérite revient à Jake Wharton et "pommedeterresaute" à https://github.com/square/otto/issues/38 pour l'approche générale. Je viens de l'implémenter avec une classe wrapper plutôt qu'une sous-classe.
Pour publier à partir de n'importe quel fil (principal ou arrière-plan) et recevoir sur le fil principal, utilisez le MainThreadBus
suivant au lieu d'un Vanilla Bus
public class MainThreadBus extends Bus {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
} else {
handler.post(new Runnable() {
@Override
public void run() {
MainThreadBus.super.post(event);
}
});
}
}
}
Ceci est basé sur la réponse d'Andy Dennie.
Il n'est pas nécessaire à la fois d'étendre et d'envelopper un objet Bus
, de faire l'un ou l'autre. Dans la réponse de Dennie, qui est en fait un wrapper, la classe de base Bus
est simplement utilisée comme une interface, toutes les fonctionnalités sont écrasées.
Cela fonctionnerait même si vous supprimiez la classe de base Bus
sauf si vous aviez justement référencé la MainThreadBus
via une référence Bus
.
Ou faites-le simplement si vous êtes sûr de publier à partir d'un fil non principal:
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
mBus.post(new myEvent());
}
});
Tout comme le dit le proverbe, "Keep It Simple and Stupid" :)
bus = nouveau bus (ThreadEnforcer.ANY); est la solution claire à ce problème. C'est tout ce que vous avez à faire.
Je l'ai fait simplement:
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
bus.post(event);
}
});
Bon codage .. :)
Meilleure classe de bus personnalisée pour moi
public class AndroidBus extends Bus {
private final Handler mainThread = new Handler(Looper.getMainLooper());
@Override
public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
} else {
mainThread.post(() -> AndroidBus.super.post(event));
}
}
}