Intereting Posts
DefaultClusterRenderer getMarker () возвращает значение null при масштабировании Что такое ffmpeg-проигрыватели с открытым исходным кодом для iOS / Android? Хранить GridView при возобновлении сна Android, как EditText работает как автозаполнение Android: невозможно найти явный класс активности … startActivity from the PreferenceActivity Как передать параметр в подкласс BroadcastReceiver? Android Studio не может создать новый проект, приуроченный к работе в режиме slave aapt Подход к заполнению расширенного списка с локальной базой данных SQlite Как избежать вызова обоих: onItemClicked и onTextChanged в AutoCompleteTextView Есть ли способ сделать изображения на кнопках с автоматическим изменением размера в соответствии с экраном? Android Unit Test с Retrofit2 и Mockito или Robolectric Использование библиотеки Android в eclipse и переход к файлам классов вместо исходного файла, находящегося в рабочей области eclipse Отладка в Sony Xperia (E2003) перестала работать внезапно Key hash для Android Android SDK Получение отклонений от заданного маршрута Google Maps?

Связь от потока к потоку с помощью GreenRobot EventBus

Только что началось с EventBus от GreenRobot .

Есть только одна вещь, которая мешает мне бороться: как вы общаетесь между разными потоками, так что метод onEventXY () фактически также выполняется в подписанной теме.

Похоже, что когда вы публикуете событие, метод onEvent подписчиков вызывается из того же потока, что и поток, на котором было отправлено событие. Это не то, чего я хочу.

Я хочу иметь возможность использовать EventBus для межпоточной связи таким образом, что фактический полученный объект события обрабатывается методом onEvent в потоке, который получил объект события.

Это возможно?

Пример:

  • mainThread
  • backGroundThread1
  • backGroundThread2

MainThread отправляет событие на EventBus, backGroundThread1 получает его в свой метод onEventXY () и выполняет код внутри своего потока (устанавливает некоторую переменную), backGroundThread2 получает его в свой метод onEventXY и выполняет код внутри своего потока (устанавливает некоторую переменную).

Если это невозможно (пока), я обречен использовать очереди потоков, такие как BlockingQueue, которые сложнее реализовать.

Есть идеи?

Solutions Collecting From Web of "Связь от потока к потоку с помощью GreenRobot EventBus"

Из документов Greenrobot на странице https://github.com/greenrobot/EventBus

BackgroundThread
Абонент будет вызываться в фоновом потоке. Если поток публикации не является основным потоком, методы обработчика событий будут вызываться непосредственно в потоке проводки. Если поток проводки является основным потоком, EventBus использует один фоновый поток, который будет передавать все его события последовательно. Обработчики событий, использующие этот режим, должны попытаться быстро вернуться, чтобы избежать блокировки фонового потока.

Async
Методы обработчика событий вызываются в отдельном потоке. Это всегда зависит от потока проводки и основного потока. События в проводке никогда не ждут методов обработчика событий, используя этот режим. Методы обработчика событий должны использовать этот режим, если их выполнение может занять некоторое время, например, для доступа к сети. Избегайте одновременного запуска большого количества длинных асинхронных методов обработчика, чтобы ограничить количество параллельных потоков. EventBus использует пул потоков для эффективного повторного использования потоков из завершенных асинхронных уведомлений обработчика событий.

При создании обратного вызова в onEvent необходимо добавить onEvent следующим образом:

  • onEventMainThread(YourEvent eventInstance) и сокращенное onEvent(YourEvent eventInstance)
    Всегда отправляет в основной поток пользовательского интерфейса
  • onEventBackgroundThread(YourEvent eventInstance)
    Это наиболее подходит для вашей проблемы
  • onEventAsync(YourEvent eventInstance)
    Всегда в новом потоке, рискованно, если вы отправляете множество событий отсюда, может легко удалять исключение Thread

У меня была та же проблема, и я использовал Looper , Handler и HandlerThread .

Это мой класс 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 String 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().toString(), Process.THREAD_PRIORITY_BACKGROUND); } if (!handlerThread.isAlive()) { handlerThread.start(); } return new BackgroundHandlerThread(handlerThread, busHandler); } } } 

Я использовал его в своей службе, но объект BackgroundHandlerThread может быть привязан к любому объекту.

 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 String 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 } 

И класс активности:

 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 String 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()); } } 

Выход журнала:

 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 

Похожее: Лучшая практика для eventbus с безопасностью потоков