Comment envoyer un événement du service à l’activité avec le bus d’événement Otto?

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.