LiveData против Handler и LocalBroadcast

У меня есть старый код Android/java, который содержит два вывода из IntentService, и эти службы не выполняются в отдельных процессах.

Вопрос о том, как вернуть результат из этих IntentService.

Один результат возврата службы с помощью Handler + Runnable, чтобы запустить код в основном цикле:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        MyApplication.get().setFoo(someThing);
    }
});

другой использует LocalBroadcastManager.getInstance(this).sendBroadcast(in); для отправки сообщения Activity и Activity подписаться через BroadcastReceiver на сообщение в onResume и отписаться в onPause.

Я прав, и в обоих случаях можно использовать LiveData для упрощения вещей?

IntentService должен создать LiveData и кому нужен результат, если observe он, и когда новые данные поступают IntentService, следует вызвать postValue, или могут быть некоторые рифы, чтобы предотвратить использование LiveData здесь?

Ответы

Ответ 1

Я думаю, что LiveData не поможет вам отправлять любые данные из Service в другие компоненты.

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

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

В ваших примерах есть два механизма связи:

  • Служба достигает статического объекта Application и устанавливает некоторые данные. Это сообщение через глобальное состояние и обычно считается анти-шаблоном.
  • Связь через LocalBroadcastManager

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

Вернуться к LiveData.

Чтобы иметь возможность получить объект LiveData из Service, вам понадобится ссылка на Service. Это обычно невозможно, если вы не привязываете Service к тому же процессу или не используете какой-то уродливый хак, который включает глобальное состояние.

Поэтому полезность LiveData в этом контексте очень ограничена.

Кстати, в то время как LocalBroadcastManager в порядке, я считаю этот механизм слишком сложным и ограничивающим. Поэтому, если Service работает в одном и том же процессе, я предпочитаю использовать EventBus для связи из Service с другими компонентами (или наоборот).

Пример такого сообщения вы можете увидеть в SQLite benchmarking application, который я написал несколько дней назад. В этом приложении TestService публикует изменения статуса и результаты тестирования на EventBus как липкие события, а TestActivity подписывается на эти события.

Ответ 2

Оба метода работают с использованием LiveData, поскольку цель LiveData - иметь его в другом потоке и все равно уведомлять пользователей о том, что что-то изменилось. Похоже, что это заменит LocalBroadcastManager.getInstance(this).sendBroadcast(in);, и ваш IntentService будет опубликован. Просто ваша деятельность или что-то, что нужно знать об изменениях, становится наблюдателем.