Eventbus android что это

Содержание
  1. Русские Блоги
  2. Подробное объяснение использования EventBus в структуре шины событий публикации / подписки Android
  3. 1. Введение
  4. 2. Что такое EventBus
  5. 3. Сравнение похожих товаров.
  6. Используйте трилогию EventBus3.0
  7. 1. Определите событие
  8. 2. Подготовьте подписчиков
  9. 3. Отправить мероприятие
  10. понять глубже
  11. 1. ThreadMode связь потоков
  12. 2. Настройте EventBusBuilder.
  13. 3.StickyEvent
  14. 4. приоритет приоритетного события
  15. 5. Прервать доставку события.
  16. 6. ускорение индекса индекса
  17. 7.NoSubscriberEvent
  18. 8. Замешательство
  19. 9. Плюсы и минусы
  20. Рекомендации
  21. 1. Управление EventBus
  22. 2. Целевые события
  23. Совет: как использовать библиотеку EventBus
  24. Предпосылки
  25. 1. Создать новый проект
  26. 2. Редактировать Манифест
  27. Связь в приложении для Android с EventBus
  28. Подписчик на событие
  29. Многозадачность в Android. Часть 2 — 7 шаблонов использования многопоточности в Android
  30. Случай 1. Выполнение запроса по сети, без необходимости ответа от сервера
  31. Вариант 1. AsyncTask или загрузчики
  32. Вариант 2. Service
  33. Вариант 3. IntentService
  34. Случай 2. Выполнение сетевого вызова и получение ответа от сервера
  35. Вариант 1. Service или IntentService
  36. Вариант 2. AsyncTask или загрузчики
  37. Вариант 3. RxJava
  38. Случай 3. Цепочка сетевых вызовов
  39. Вариант 1. AsyncTask или загрузчики
  40. Вариант 2. RxJava с использованием flatMap
  41. Случай 4. Общение c UI потоком из другого потока
  42. Вариант 1. RxJava внутри сервиса
  43. Вариант 2. BroadcastReceiver
  44. Вариант 3. Использование Handler
  45. Вариант 3. Использование EventBus
  46. Случай 5. Двусторонняя связь между потоками на основе действий пользователя
  47. Вариант 1. Использование EventBus
  48. Вариант 2. Использование BoundService
  49. Случай 6. Выполнение действий параллельно и получение результатов
  50. Случай 7. Запрос к локальной SQLite базе данных
  51. Заключение

Русские Блоги

Подробное объяснение использования EventBus в структуре шины событий публикации / подписки Android

1. Введение

Однажды слой за слоем бизнес-логики приводил меня в недоумение, один обратный вызов за другим вызывали у вас головокружение, а один параметр за другим сбивали вас с толку. EventBus, фреймворк с низкой степенью связи, который пугает.

2. Что такое EventBus

EventBus — это шина сообщений, реализованная в режиме наблюдателя, используемая для упрощения программных компонентов и взаимодействия потоков, и может легко переключать потоки и открывать потоки. Отличие EventBus3.0 от предыдущей версии заключается в добавлении аннотации @Subscribe, которая заменяет предыдущее соглашение об именах.

3. Сравнение похожих товаров.

наименование товара Разработчик Замечания
EventBus greenrobot Максимум пользователей, краткий, удобный, небольшой, краткий и понятный документ
Guava google Огромная библиотека инструментов, EventBus — это всего лишь небольшая функция
otto square Вилка гуавы, многие ее используют
AndroidEventBus Хэ Хунхуэй Имитация разработки EventBus

Используйте трилогию EventBus3.0

1. Определите событие

2. Подготовьте подписчиков

3. Отправить мероприятие

понять глубже

1. ThreadMode связь потоков

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

2. Настройте EventBusBuilder.

EventBus предоставляет множество настроек. В обычных условиях настраивать его не нужно. Однако, если у вас есть другие требования, такие как управление выводом журнала во время разработки, а не выводом во время выпуска, сбой из-за ошибки во время разработки и выпуск во время выпуска Никакого сбоя . и т. Д.
EventBus предоставляет реализацию по умолчанию, но не синглтон.

3.StickyEvent

StickyEvent сохраняет последнее сообщение в памяти, отменяет исходное сообщение и выполняет последнее сообщение. Оно будет выполнено только после регистрации. Если регистрации нет, сообщение всегда будет храниться в памяти.

Вы также можете управлять StickyEvent вручную

Здесь у вас может возникнуть вопрос,
Могут ли подписчики с StickyEvent = true получать события публикации?
Могут ли подписчики StickyEvent = false получать события postSticky?
Просмотр обнаружения исходного кода

Обнаружено, что метод post не фильтрует StickyEvent, а postSticky вызывает метод post, поэтому независимо от того, является ли post или postSticky StickyEvent истинным или ложным, он будет выполнен

4. приоритет приоритетного события

5. Прервать доставку события.

6. ускорение индекса индекса

EventBus использует аннотацию, которая по умолчанию генерирует код и индексы во время компиляции.
После добавления индекса он будет запущен во время компиляции, и соответствующий код будет автоматически сгенерирован.
ps: из-за ограничений apt аннотации в анонимном внутреннем классе не будут распознаваться и будут автоматически ухудшены, чтобы отражать их во время выполнения. В это время эффективность будет снижена
Адрес официального сайта EventBus

Поскольку kotlin использует аннотации по-разному, вам нужно использовать kapt

ps: если необходимо проиндексировать несколько модулей, указанные выше три apts должны быть добавлены к каждому модулю, и импорт пакета не нужно повторять

Таким образом, код будет автоматически сгенерирован после компиляции.

Метод события создается путем отражения во время компиляции и сохраняется на карте. Когда событие отправляется, вызывается getSubscriberInfo для получения карты.

7.NoSubscriberEvent

Если событие подписчика не найдено, вы можете указать, следует ли отправлять NoSubscriberEvent по умолчанию через EventBusBuilder, который по умолчанию включен.

8. Замешательство

9. Плюсы и минусы

Простая, удобная, компактная, понятная документация, низкое энергопотребление, настраиваемая прочность линии, низкое сцепление

Это определенно не шутка. Связь EventBus слишком мала. Если она не контролируется и не управляется, вы не будете знать, куда идет отправленное вами сообщение. Я не знаю, куда будет отправлено ваше сообщение. Если у вас нет хорошего способа решить эту проблему, рекомендуется не использовать слишком много.

Рекомендации

1. Управление EventBus

EventBus запускается для создания нескольких, затем, чтобы уточнить жизненный цикл события, использовать разные EventBus в соответствии с разными жизненными циклами?

2. Целевые события

Инкапсулируйте данные в класс событий. Все события помещены в один пакет. Если событий слишком много, события одного модуля можно рассматривать с помощью статических внутренних классов или субподряда.

Обратите внимание, что если они не одного типа, они должны быть упакованы как событие. Необходимо учитывать определенные бизнес-сценарии и условия кода. Например, поведение событий и жизненные циклы событий различаются. При необходимости лучше записать пакеты в два события.

Источник

Совет: как использовать библиотеку EventBus

Создание приложения для Android с несколькими активными компонентами, взаимодействующими друг с другом, может быть утомительным. Чтобы сэкономить время, разработчики часто используют тесно связанные компоненты в своих приложениях. EventBus — это популярная библиотека с открытым исходным кодом, созданная для решения этой проблемы с использованием шаблона издатель / подписчик .

Используя библиотеку EventBus, вы можете передавать сообщения из одного класса в один или несколько классов всего за несколько строк кода. Более того, все участвующие классы полностью отделены друг от друга, что приводит к тому, что код становится менее сложным, а его легче поддерживать и отлаживать.

В этом кратком совете вы узнаете, как использовать библиотеку EventBus, создав простое приложение для Android, отображающее состояние зарядки устройства. Поскольку изменения в статусе начисления платы являются системными событиями, приложение будет иметь Activity которая должна получать информацию от BroadcastReceiver — идеальный сценарий для использования шины событий.

Предпосылки

Убедитесь, что у вас установлена ​​Eclipse ADT Bundle. Вы можете скачать его с сайта разработчика Android .

1. Создать новый проект

Запустите Eclipse и создайте новое приложение для Android. Назовите приложение EventBusSample . Выберите уникальное имя пакета и установите Минимальный необходимый SDK для Android 2.2 и Target SDK для Android 4.4 .

Мы собираемся создать действие самостоятельно, поэтому отмените выбор « Создать действие» и нажмите « Готово» .

2. Редактировать Манифест

Это приложение имеет один BroadcastReceiver который отвечает на следующие действия:

Источник

Связь в приложении для Android с EventBus

Типичное приложение для Android, как правило, состоит из множества слоев, модулей или структур, таких как фрагменты, действия, докладчики и службы. Эффективная связь между этими компонентами может стать затруднительной, если они тесно связаны друг с другом.

На нижнем уровне архитектуры вашего приложения, например, в базе данных, когда происходит какое-либо действие, вы можете отправить данные на более высокий уровень, такой как представление. Для этого вы можете создать интерфейс слушателя, асинхронные задачи или обратные вызовы. Все это будет работать, но у них есть некоторые существенные недостатки:

  1. прямая или жесткая связь
  2. индивидуальная регистрация и отмена регистрации нескольких зависимостей
  3. повторение кода
  4. сложность в тестировании
  5. повышенный риск ошибок

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

Чтобы использовать Greenrobot EventBus, вам необходимо сначала добавить его в файл build.gradle модуля приложения , включить compile ‘org.greenrobot: eventbus :3.0.0’ , а затем синхронизировать ваш проект.

Подписчик на событие

Подписчик просто подписывается на событие, регистрируясь в шине событий, а также может отменить регистрацию этого события. Чтобы стать подписчиком, вы должны сделать три основных вещи:

1. Зарегистрируйте абонента в шине событий с помощью register() . Это сообщает шине событий, что вы хотите начать получать события. В onStart() это происходит в onStart() , а во фрагменте — в onAttact(Activity activity) .

Источник

Многозадачность в Android. Часть 2 — 7 шаблонов использования многопоточности в Android

31.08.2017 в 21:20

Случай 1. Выполнение запроса по сети, без необходимости ответа от сервера

Иногда вы можете отправить запрос API на сервер, не беспокоясь о его ответе. Например, вы можете отправлять токен устройства для пуш-уведомлений на ваш сервер.

Т.к. это включает в себя создание запроса по сети, вы должны сделать это из потока, отличного от основного.

Вариант 1. AsyncTask или загрузчики

Вы можете использовать AsyncTask или загрузчики для выполнения вызова, и это будет работать.

Однако AsyncTask и загрузчики зависят от жизненного цикла активности. Это означает, что вам нужно будет либо дождаться завершения вызова, либо попытаться помешать пользователю покинуть активность или надеяться, что он будет выполнен до того, как активность будет уничтожена.

Вариант 2. Service

Service может лучше подходить для этого варианта использования, поскольку он не привязан к какой-либо активности. Поэтому он сможет продолжить сетевой вызов даже после уничтожения активности. Плюс, так как ответ с сервера не нужен, сервис здесь тоже не ограничивается.

Однако, поскольку сервис начнет работать в потоке пользовательского интерфейса, вам все равно нужно будет управлять потоками. Вам также необходимо убедиться, что сервис остановлен после завершения сетевого вызова.

Это потребует больше усилий, чем это необходимо для такого простого действия.

Вариант 3. IntentService

Это, на мой взгляд, было бы лучшим вариантом.

Поскольку IntentService не привязан к какой-либо активности и работает на потоке, отличном от UI, он отлично удовлетворяет нашим потребностям. Кроме того, IntentService автоматически останавливается, поэтому нет необходимости вручную управлять им.

Случай 2. Выполнение сетевого вызова и получение ответа от сервера

Этот вариант использования, вероятно, более распространен. Например, вы можете вызвать API в фоновом режиме и использовать его ответ для заполнения полей на экране.

Вариант 1. Service или IntentService

Хотя Service или IntentService хорошо справлялись с предыдущим вариантом использования, использование их здесь не было бы хорошей идеей. Попытка получить данные из Service или IntentService в основном потоке пользовательского интерфейса сделает это очень сложной задачей.

Вариант 2. AsyncTask или загрузчики

AsyncTask или загрузчики выглядели бы здесь очевидным решением. Они просты в использовании — просты и понятны.

Однако при использовании AsyncTask или загрузчиков вы заметите, что необходимо написать шаблонный код. Более того, обработка ошибок становится основной задачей этих компонентов. Даже при простом сетевом вызове вам нужно знать о возможных исключениях, ловить их и действовать соответственно. Это заставляет нас обернуть наш ответ в кастомном классе, содержащем данные, с возможной информацией об ошибке, а флаг будет указывать, было ли действие успешным или нет.

Это довольно много работы для каждого вызова. К счастью, теперь доступно гораздо лучшее и простое решение: RxJava.

Вариант 3. RxJava

Возможно вы слышали о библиотеке RxJava, разработанной Netflix. Это почти волшебство на Java.

RxAndroid позволяет использовать RxJava в Android и позволяет работать с асинхронными задачами. Вы можете узнать больше о RxJava на Android здесь. RxJava предоставляет два компонента: Observer и Subscriber .

Наблюдатель — это компонент, который содержит какое-то действие. Он выполняет это действие и возвращает результат, если он удался, ошибка, если он не работает.

Подписчик, с другой стороны, является компонентом, который может получить результат (или ошибку) от наблюдаемого, подписавшись на него.

В RxJava вы сначала создаете наблюдателя:

Как только наблюдатель будет создан, вы можете подписаться на него.

С помощью библиотеки RxAndroid вы можете контролировать поток, в котором вы хотите выполнить действие наблюдателя, и поток, в котором вы хотите получить ответ (т. е. результат или ошибку).

Вы связываетесь с наблюдателем этими двумя функциями:

Планировщики — это компоненты, которые выполняют действие в определенном потоке. AndroidSchedulers.mainThread() — это планировщик, связанный с основным потоком.

Учитывая, что наш вызов API — это mRestApi.getData() , и он возвращает объект Data, базовый вызов может выглядеть так:

Даже не вникая в другие преимущества использования RxJava, вы уже можете видеть, как RxJava позволяет нам писать более зрелый код, абстрагируя сложность потоковой передачи.

Случай 3. Цепочка сетевых вызовов

Для сетевых вызовов, которые необходимо выполнить последовательно (т.е. когда каждая операция зависит от ответа / результата предыдущей операции), вам нужно быть особенно осторожным при создании спагетти кода.

Например, вам может потребоваться выполнить запрос к API с помощью токена, который вам нужно сначала получить через другой запрос к API.

Вариант 1. AsyncTask или загрузчики

Использование AsyncTask или загрузчиков почти наверняка приведет к спагетти коду. Общую функциональность будет трудно реализовать правильно, и для вашего проекта потребуется огромное количество избыточного шаблонного кода.

Вариант 2. RxJava с использованием flatMap

В RxJava оператор flatMap берет исходящее значение из наблюдаемого источника и возвращает другого наблюдателя. Вы можете создать одного наблюдателя, а затем другого, и использовать исходящее значение из первого, для их связи.

Шаг 1. Создайте наблюдателя, который извлекает токен:

Шаг 2. Создайте наблюдателя, который получает данные с помощью токена:

Шаг 3. Цепочка двух наблюдателей вместе и подписка:

Обратите внимание, что использование этого подхода не ограничивается сетевыми вызовами; Он может работать с любым набором действий, которые должны выполняться в последовательности, но в отдельных потоках.

Все приведенные выше примеры использования довольно просты. Переключение между потоками происходило только после завершения каждой задачи. Более продвинутые сценарии, например, когда два или более потока должны активно взаимодействовать друг с другом, могут также поддерживаться этим подходом.

Случай 4. Общение c UI потоком из другого потока

Рассмотрим сценарий, в котором вы хотите загрузить файл и обновить пользовательский интерфейс после его завершения.

Поскольку загрузка файла может занять много времени, нет необходимости держать пользователя в ожидании. Вы можете использовать сервис и, возможно, IntentService для реализации функциональности в нем.

Однако, в этом случае, более сложная задача заключается в возможности вызвать метод в потоке пользовательского интерфейса после завершения загрузки файла (который был выполнен в отдельном потоке).

Вариант 1. RxJava внутри сервиса

RxJava, как самостоятельно, так и внутри IntentService , может быть не идеальным решением. Вам нужно будет использовать механизм обратного вызова при подписке на Observable , а IntentService построен для выполнения простых синхронных, а не обратных вызовов.

С другой стороны, с помощью Service вам необходимо будет вручную остановить службу, что потребует дополнительной работы.

Вариант 2. BroadcastReceiver

Android предоставляет компонент, который может слушать глобальные события (например, события батареи, сетевые события и т.д.), А также настраиваемые события. Вы можете использовать этот компонент для создания настраиваемого события, которое запускается при завершении загрузки.

Для этого вам нужно создать собственный класс, который расширяет BroadcastReceiver , регистрирует его в манифесте и использует Intent и IntentFilter для создания настраиваемого события. Чтобы инициировать событие, вам понадобится метод sendBroadcast .

Такой подход является жизнеспособным вариантом. Но, как вы заметили, это связано с некоторой работой, и слишком много передач могут замедлить работу.

Вариант 3. Использование Handler

Handler — это компонент, который может быть присоединен к потоку, а затем быть использованным для выполнения некоторых действий в этом потоке с помощью простых сообщений или Runnable задач. Он работает совместно с другим компонентом — Looper , который отвечает за обработку сообщений в конкретном потоке.

Когда Handler создается, он может получить объект Looper в конструкторе, который указывает, к какому потоку он прикреплен. Если вы хотите использовать Handler, прикрепленный к основному потоку, вам нужно использовать looper, связанный с основным потоком, вызывая Looper.getMainLooper() .

В этом случае для обновления пользовательского интерфейса из фонового потока вы можете создать Handler, подключенный к потоку пользовательского интерфейса, а затем опубликовать действие как Runnable :

Этот подход намного лучше, чем первый, но есть еще более простой способ сделать это…

Вариант 3. Использование EventBus

EventBus — это популярная библиотека от GreenRobot, позволяет компонентам безопасно связываться друг с другом. Поскольку наш вариант использования — это тот, где мы хотим обновить интерфейс, это может быть самым простым и безопасным способом.

Шаг 1. Создайте класс событий. Например, UIEvent .

Шаг 2. Подпишитесь на событие.

Шаг 3. Отправьте событие: EventBus.getDefault (). Post (новый UIEvent ());

С помощью параметра ThreadMode в аннотации вы указываете поток, по которому вы хотите подписаться на это событие. В нашем примере здесь мы выбираем основной поток, так как мы хотим, чтобы получатель события смог обновить интерфейс.

Вы можете структурировать свой класс UIEvent , чтобы он содержал дополнительную информацию по мере необходимости.

В активности / фрагменте:

Используя библиотеку EventBus , связь между потоками становится намного проще.

Случай 5. Двусторонняя связь между потоками на основе действий пользователя

Предположим, вы создаете медиаплеер и хотите, чтобы он продолжал воспроизводить музыку, даже когда экран приложения закрыт. В этом случае вы хотите, чтобы пользовательский интерфейс мог взаимодействовать с медиа-потоком (например, играть, приостанавливать и другие действия), а также требовать, чтобы медиа-поток обновлял пользовательский интерфейс на основе определенных событий (например, ошибка, состояние буферизации, и т.д).

Полный пример медиаплеера выходит за рамки этой статьи. Однако вы можете найти хорошие материалы здесь и здесь.

Вариант 1. Использование EventBus

Здесь вы можете использовать EventBus . Однако, как правило, не безопасно отправлять событие из потока пользовательского интерфейса и получать его в сервисе. Это связано с тем, что вы не можете узнать, работает ли сервис, когда вы отправили сообщение.

Вариант 2. Использование BoundService

BoundService — это служба, связанная с активностью / фрагментом. Это означает, что активность / фрагмент всегда знает, работает служба или нет и получает доступ к публичным методам службы.

Чтобы реализовать его, вам необходимо создать настраиваемый Binder внутри службы и создать метод, который возвращает службу.

Чтобы связать активность со службой, вам необходимо реализовать ServiceConnection , который является классом, контролирующим статус службы, и использовать метод bindService для привязки:

Здесь вы можете найти полный пример реализации.

Чтобы связаться со службой, когда пользователь нажимает кнопку «Воспроизведение» или «Пауза», вы можете привязать их к службе, а затем вызвать соответствующий общедоступный метод в службе.

Когда есть мультимедийное событие, и вы хотите сообщить об этом активности / фрагменту, вы можете использовать один из более ранних подходов (например, BroadcastReceiver, Handler или EventBus).

Случай 6. Выполнение действий параллельно и получение результатов

Предположим, вы строите туристическое приложение, и вы хотите показать достопримечательности на карте, полученные из нескольких источников (разные поставщики данных). Поскольку не все источники могут быть надежными, вы можете проигнорировать те, которые потерпели неудачу, и продолжать отображать карту в любом случае.

Чтобы распараллелить процесс, каждый вызов к API должен выполняться в другом потоке.

Вариант 1: Использование RxJava

В RxJava вы можете комбинировать несколько наблюдателей в одном с помощью операторов merge() или concat() . Затем вы можете подписаться на «merged» наблюдатели и ждать всех результатов.

Но, этот подход не будет работать должным образом. Если один вызов к API завершится неудачно, объединенный (merged) наблюдатель сообщит об общем сбое.

Вариант 2. Использование Java-компонентов

ExecutorService в Java создает фиксированное (настраиваемое) количество потоков и одновременно выполняет задачи на них. Служба возвращает объект Future , который в конечном итоге возвращает все результаты с помощью метода invokeAll() .

Каждая задача, которую вы отправляете в ExecutorService , должна содержаться в интерфейсе Callable , который является интерфейсом для создания задачи, которая может генерировать исключение.

Получив результаты от invokeAll() , вы можете проверить каждый результат и действовать соответствующим образом.

Скажем, например, что у вас есть три типа данных, поступающих из трех разных конечных точек, и вы хотите сделать три параллельных вызова:

Таким образом, вы выполняете все действия параллельно. Поэтому вы можете проверять ошибки в каждом действии отдельно и игнорировать отдельные сбои, если это необходимо.

Этот подход проще, чем использование RxJava. Это проще, короче и не отменяет все действия из-за одного исключения.

Случай 7. Запрос к локальной SQLite базе данных

При работе с локальной базой данных SQLite, рекомендуется производить вызовы из фонового потока, поскольку запросы к базе данных (особенно с большими базами данных или сложными запросами) могут занимать много времени, что приводит к замораживанию пользовательского интерфейса.

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

Вариант 1: Использование RxJava

Вы можете использовать RxJava и получать данные из базы данных, так же, как мы получаем данные из нашего back-end:

Вы можете использовать наблюдателя, возвращаемого getLocalDataObservable() следующим образом:

Хотя это, безусловно, хороший подход, есть один, который еще лучше, поскольку есть компонент, который построен именно для этого самого случая.

Вариант 2: Использование CursorLoader + ContentProvider

Android предоставляет CursorLoader , собственный компонент для загрузки данных из SQLite и управления соответствующим потоком. Это Loader , который возвращает Cursor , который мы можем использовать для получения данных, вызывая простые методы, такие как getString() , getLong() и т.д.

CursorLoader работает с компонентом ContentProvider . Этот компонент предоставляет множество возможностей для работы с базой данных в режиме реального времени (например, уведомления об изменениях, триггеры и т.д.), что позволяет разработчикам более легко реализовать более удобный пользовательский интерфейс.

Заключение

Android предоставляет множество способов обработки и управления потоками, но ни один из них не является серебрянной пулей.

Выбор правильного подхода к многопоточности, в зависимости от вашего варианта использования, может сделать все возможное, чтобы общее решение было легко реализовано и понято. Нативные компоненты подходят для некоторых случаев, но не для всех. То же самое относится к причудливым сторонним решениям.

Надеюсь, вы найдете эту статью полезной при работе над следующим Android проектом. Поделитесь с нами своим опытом потоковой передачи в Android или в любом случае, когда вышеупомянутые решения работают хорошо — или нет, если на то пошло — в комментариях ниже.

Источник

Читайте также:  Как убрать вибрацию при нажатии клавиатуры андроид
Оцените статью