Simple BusProvider.getInstance().post()
apporte une exception, pas main thread
. Comment envoyer un événement du service à l’activité avec le bus d’événement Otto?
Pour publier depuis n’importe quel thread (principal ou arrière-plan) et recevoir sur le thread 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); } }); } } }
Note: Jake Wharton et “pommedeterresaute” à https://github.com/square/otto/issues/38 méritent une note d’approche générale. Je viens de l’implémenter avec une classe wrapper plutôt qu’une sous-classe.
Pour publier depuis n’importe quel thread (principal ou d’arrière-plan) et recevoir sur le thread principal, utilisez le MainThreadBus
suivant MainThreadBus
lieu d’un Bus
vanille
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 object Bus
, de faire l’un ou l’autre. Dans la réponse de Dennie, qui est effectivement un wrapper, la classe de base du Bus
est simplement utilisée comme une interface, toutes les fonctionnalités sont écrasées.
Cela fonctionnerait même si vous MainThreadBus
la classe de base du Bus
moins que vous ne fassiez référence au MainThreadBus
via une référence de Bus
.
Ou faites-le simplement si vous êtes sûr de publier à partir d’un thread non principal:
new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { mBus.post(new myEvent()); } });
Comme dit le proverbe, “Keep It Simple and Stupid” 🙂
bus = new Bus (ThreadEnforcer.ANY); est la solution claire à ce problème. C’est tout ce que vous avez à faire.
Meilleure mise en œuvre de la 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)); } } }
Je l’ai fait simplement:
Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { bus.post(event); } });
Heureux codage .. 🙂
Créez simplement le BasicBus
avec ThreadEnforcer.NONE
pour publier un événement à partir de threads non principaux. Le ThreadEnforcer.MAIN
mentionné est exactement le contraire (et la valeur par défaut), qui accepte uniquement les publications du thread principal.