Как обновить пользовательский интерфейс из службы Android с помощью RxJava/RxAndroid

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

На самом деле я думаю, что общий способ — использовать BroadcastReciever или CallBack из Activity. Но я где-то слышал об использовании RxJava (программирование ReactiveX) и класса посредника (и Dagger для его внедрения как в сервис, так и в активность), о чем говорится ниже.

Итак, мой вопрос: как обращаться с RxJava с этой кучей вещей? Любые образцы кода? Есть ли другой эффективный способ, кроме использования намерений?

Ресурс: более эффективный способ обновления пользовательского интерфейса из службы, чем намерения. ? [см. первое обновление ответа]


person Amirhossein Kazemnejad    schedule 20.11.2015    source источник
comment
Лично я предпочитаю использовать службу обмена сообщениями: developer.android.com/reference/android/os /Messenger.html   -  person mjp66    schedule 21.11.2015
comment
Я думал, что где-то здесь у меня есть пример использования Messenger, думаю, нет, но вот хороший пост с подробным описанием его использования: and-service-using-messaging" title="пример связи между действием и службой с использованием обмена сообщениями"> stackoverflow.com/questions/4300291/   -  person mjp66    schedule 21.11.2015
comment
просто используйте шаблон локальной привязанной службы, нет необходимости в каких-либо внешних библиотеках, и это самое быстрое решение   -  person pskink    schedule 21.11.2015
comment
@pskink, вы имеете в виду передачу обратного вызова связанной службе и использование ее для получения нового прогресса загрузки?   -  person Amirhossein Kazemnejad    schedule 21.11.2015
comment
да, это именно то, что я имею в виду, но если вы храните свои загрузки в какой-то базе данных sqlite, вы можете использовать CursorLoader, который запрашивает ваш пользовательский ContentProvider, и служба обновляет/вставляет/удаляет вашего провайдера, в этом случае нет необходимости в каких-либо обратных вызовах   -  person pskink    schedule 21.11.2015
comment
@AmirHoseinKazemNejad Это не совсем то, что вы ищете, но, возможно, эта статья вдохновит вас donnfelker. com/rxjava-with-aidl-services   -  person LordRaydenMK    schedule 21.11.2015


Ответы (2)


Требуется для RxJava/RxAndroid

1) НАБЛЮДАЕМЫЕ 2) НАБЛЮДАТЕЛИ 3) ПОДПИСАТЬСЯ

Спланируйте, где вам нужно разместить свои 1, 2, 3,

OBSERVABLES идут туда, где создаются данные, поэтому в вашем случае SERVICE

НАБЛЮДАТЕЛИ отправляются туда, где данные должны потребляться (или отображаться), так что это ваша АКТИВНОСТЬ.

ПОДПИСАТЬСЯ можно везде, где у вас есть доступ к ОБСЛУЖИВАЕМЫМ И НАБЛЮДАЮЩИМ, поэтому давайте воспользуемся АКТИВНОСТЬЮ для этого.

Процедура и код:

Во-первых, подготовьте свой OBSERVABLE к обслуживанию, как это

class MyService extends Service {
    static PublishSubject<String> data = PublishSubject.create();

   @Override
   public void onStarCommand(Intent intent,int i, int j){
        # DO THIS ANYWHER WHERE YOU GENERATE DATA 
        data.onNext("Hello");
   }

   public static Observable<String> getObservable(){
      return data;
   }
}

Во-вторых, подготовьте свой OBSERVER (и OBSERVABLE) в Activity onCreate.

Observable<String> observable = MyService.getObservable();
Observer<String> observer = new Observer<String>() {
        @Override
        public void onCompleted() {
            Log.d(TAG, "onCompleted: ");
        }

        @Override
        public void onError(Throwable e) {
            Log.e(TAG, "onError: ",e);
        }

        @Override
        public void onNext(String text) {
            Log.d(TAG, "DATA reveived here: "+text);
        }
    };

Наконец, свяжите OBSERVER и OBSERVABLE в Activity, иначе Observable не ответит, используйте это снова в onCreate.

observable.subscribe(observer);

ГОТОВО, теперь, когда даже данные запускаются из службы с помощью onNext(), данные поступают в действие

person Ujju    schedule 16.04.2018
comment
А как это сделать без статических полей? - person Mikel; 05.03.2019
comment
public void onCompleted() должно быть public void onComplete(). Также отсутствует метод onSubscribe(). - person Farrukh Najmi; 10.03.2019
comment
приложение аварийно завершает работу, когда действие/фрагмент уничтожено или неактивно... как с этим справиться? - person user1090751; 13.08.2020

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

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

person npace    schedule 26.10.2016
comment
Можете ли вы объяснить свой комментарий или привести пример? - person Zulqurnain Jutt; 17.11.2016
comment
Плохой ответ. Observable не является сериализованным объектом, поэтому не уверен, что он будет работать, особенно если сервис предназначен для взаимодействия между процессами. Не будет работать. - person msangel; 30.01.2017
comment
Взаимодействие между процессами выходит за рамки этого вопроса. В противном случае это в основном то же самое, что и предоставление экземпляра службы через Binder, и служба также не сериализуема. - person npace; 01.02.2017
comment
@LeonardoAcevedo, не проверял, но не должно работать - person msangel; 20.02.2017
comment
@msangel для локальной связанной службы не должно быть необходимости в сериализации, как вы думаете, это сработает в этом случае? - person Leo supports Monica Cellio; 21.02.2017