Communication d’un fil à l’autre à l’aide de GreenRobot EventBus

Je viens juste de commencer avec EventBus de GreenRobot.

Il n’ya qu’une chose qui m’empêche de continuer à lutter: comment communiquer entre différents threads pour que la méthode onEventXY () soit également exécutée dans le thread souscrit.

Il semble que lorsque vous publiez un événement, la méthode onEvent des abonnés soit appelée à partir du même fil que le fil sur lequel l’événement a été publié. Ce n’est pas ce que je veux.

Je veux pouvoir utiliser EventBus pour la communication inter-threads de telle sorte que l’object événement réellement reçu soit géré par la méthode onEvent au sein du thread ayant reçu l’object event.

Est-ce possible?

Exemple:

  • mainThread
  • backGroundThread1
  • backGroundThread2

MainThread publie un événement sur EventBus, backGroundThread1 le reçoit dans sa méthode onEventXY () et exécute le code dans son propre thread (définit une variable), backGroundThread2 le reçoit dans sa méthode onEventXY et exécute le code dans son propre thread (définit une variable).

Si cela n’est pas (encore) possible, je suis condamné à utiliser des files d’attente de threads, comme BlockingQueue, qui est plus difficile à implémenter.

Des idées?

Des documents Greenrobot à l’ adresse https://github.com/greenrobot/EventBus

BackgroundThread
L’abonné sera appelé dans un fil de discussion. Si le fil de publication n’est pas le fil principal, les méthodes du gestionnaire d’événements seront directement appelées dans le fil de publication. Si le fil de publication est le fil principal, EventBus utilise un seul fil en arrière-plan qui transmettra tous ses événements de manière séquentielle. Les gestionnaires d’événements utilisant ce mode doivent essayer de revenir rapidement afin d’éviter de bloquer le thread d’arrière-plan.

Async
Les méthodes de gestionnaire d’événements sont appelées dans un thread séparé. Ceci est toujours indépendant du fil de publication et du fil principal. La publication d’événements n’attend jamais que les méthodes du gestionnaire d’événements utilisent ce mode. Les méthodes de gestionnaire d’événements doivent utiliser ce mode si leur exécution peut prendre un certain temps, par exemple pour un access réseau. Évitez de déclencher simultanément un grand nombre de méthodes de gestionnaires asynchrones de longue durée afin de limiter le nombre de threads simultanés. EventBus utilise un pool de threads pour réutiliser efficacement les threads à partir des notifications de gestionnaire d’événement asynchrones terminées.

Lors de la création d’un rappel, le suffixe du nom doit être ajouté à onEvent comme suit:

  • onEventMainThread(YourEvent eventInstance) et onEvent(YourEvent eventInstance)
    envoie toujours dans le fil principal de l’interface utilisateur
  • onEventBackgroundThread(YourEvent eventInstance)
    cela convient le mieux à votre problème
  • onEventAsync(YourEvent eventInstance)
    toujours dans un nouveau fil, risqué si vous envoyez une multitude d’événements à partir d’ici, peut bash une exception Thread facilement

J’ai eu le même problème et j’ai utilisé Looper , Handler et HandlerThread .

C’est ma classe BackgroundHandlerThread:

 import android.annotation.TargetApi; import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.os.Process; import android.util.Log; import java.lang.reflect.Method; import java.util.UUID; public class BackgroundHandlerThread extends Handler { private static final Ssortingng TAG = BackgroundHandlerThread.class.getSimpleName(); private HandlerThread handlerThread; private Object busHandler; public BackgroundHandlerThread(HandlerThread handlerThread, Object busHandler) { super(handlerThread.getLooper()); this.handlerThread = handlerThread; this.busHandler = busHandler; } public void onEvent(Object event) { Log.d(TAG, "onEvent(Object), thread: " + Thread.currentThread().getId() + ", class: " + event.getClass().getName()); Message message = obtainMessage(); message.obj = event; sendMessage(message); } @Override public void handleMessage(Message msg) { Method[] aClassMethods = busHandler.getClass().getDeclaredMethods(); for (Method m : aClassMethods) { if (m.getName().equals("onHandlerThreadEvent")) { if (m.getParameterTypes().length == 1 && m.getParameterTypes()[0].equals(msg.obj.getClass())) { try { m.invoke(busHandler, msg.obj); } catch (Exception e) { Log.wtf(TAG, e); } } } } } public boolean quit() { return handlerThread.quit(); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public boolean quitSafely() { return handlerThread.quitSafely(); } public static class Builder { private HandlerThread handlerThread; private Object busHandler; public Builder(Object busHandler) { this.busHandler = busHandler; } public Builder setHandlerThread(HandlerThread handlerThread) { this.handlerThread = handlerThread; return this; } public BackgroundHandlerThread build() { if (handlerThread == null) { handlerThread = new HandlerThread("BackgroundHandlerThread: " + UUID.randomUUID().toSsortingng(), Process.THREAD_PRIORITY_BACKGROUND); } if (!handlerThread.isAlive()) { handlerThread.start(); } return new BackgroundHandlerThread(handlerThread, busHandler); } } } 

Je l’ai utilisé dans mon service, mais l’object BackgroundHandlerThread peut être lié à n’importe quel object.

 import android.app.Service; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; import de.greenrobot.event.EventBus; public class DeviceService extends Service { private static final Ssortingng TAG = DeviceService.class.getSimpleName(); private BluetoothDevice bluetoothDevice; private BackgroundHandlerThread handlerThread; private boolean connected = false; //region Lifecycle @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate, thread: " + Thread.currentThread().getId()); handlerThread = new BackgroundHandlerThread.Builder(this).build(); EventBus.getDefault().register(handlerThread); } @Override public void onDestroy() { EventBus.getDefault().unregister(handlerThread); handlerThread.quit(); super.onDestroy(); } //endregion public void onHandlerThreadEvent(ConnectToDeviceEvent event) { Log.d(TAG, "onHandlerThreadEvent, thread: " + Thread.currentThread().getId()); connected = true; bluetoothDevice = event.device; EventBus.getDefault().post(new ConnectionStateChangedEvent(bluetoothDevice, connected)); } //region Static manipulation public static void startService(Context context) { Intent intent = new Intent(context, DeviceBinder.class); context.startService(intent); } //endregion } 

Et classe d’activité:

 import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.util.Log; import de.greenrobot.event.EventBus; public class MainActivity extends Activity { private static final Ssortingng TAG = MainActivity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.startButton).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d(TAG, "onStartClick, thread: " + Thread.currentThread().getId()); EventBus.getDefault().post(new ConnectToDeviceEvent(application.getCurrentStateProvider().getDevice())); } }); DeviceService.startService(this); } @Override protected void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override protected void onStop() { EventBus.getDefault().unregister(this); super.onStop(); } public void onEventMainThread(ConnectionStateChangedEvent event) { Log.d(TAG, "onEventMainThread(ConnectionStateChangedEvent), thread: " + Thread.currentThread().getId()); } } 

Journal de sortie:

 D/MainActivity: onStartClick, thread: 1 D/BackgroundHandlerThread: onEvent(Object), thread: 1, class: ConnectToDeviceEvent D/DeviceService: onHandlerThreadEvent, thread: 4399 D/BackgroundHandlerThread: onEvent(Object), thread: 4399, class: ConnectionStateChangedEvent D/MainActivity: onEventMainThread(ConnectionStateChangedEvent), thread: 1 

Similaire: Meilleure pratique pour Eventbus avec sécurité du thread