2015-11-19 2 views
2

Я работаю над приложением Android, которое извлекает два разных объекта через API, к которому я обращаюсь через RxJava Observables. Чтобы обновить пользовательский интерфейс, мне нужны и результаты.RxJava: функция вызова при завершении двух наблюдаемых с различными типами результатов

Как я могу запустить функцию, как только оба наблюдателя завершатся? Кажется, что такие функции, как merge, делают то, что я планирую, но насколько я вижу, они работают только для Observables с одинаковым типом результата или для него нужен составной объект, который может представлять оба типа.

Простой пример:

Observable.just("Hello world") 
     .subscribe(new Action1<String>() { 
      @Override 
      public void call(String s) { 
       System.out.println(s); 
      } 
     }); 
Observable.just(1, 2, 3, 4, 5, 6) 
     .subscribe(new Action1<Integer>() { 
      @Override 
      public void call(Integer i) { 
       System.out.println(i); 
      } 
     }); 

Что мне нужно сделать, чтобы запустить System.out.println("Finished!") как только оба Наблюдаемые выполнили свою задачу?

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

+0

Взгляните: http://reactivex.io/documentation/operators/zip.html и http://reactivex.io/documentation/operators/combinelatest.html – Than

+0

Посмотрите на .zip(). –

+0

'zip' не будет работать в этом случае, так как первый Observable возвращает меньше результатов, чем второй. Я мог бы использовать 'combLatest', но в этом случае это тоже не очень хорошо. Я просто хочу получить уведомление, если оба Observables будут закончены. – Strayer

ответ

1

Версия 2: испускаемые элементы обрабатываются как «боковые» действия, только событие onCompleted переходит к объединенному наблюдаемому.

Observable<String> stringObservable = Observable.just("Hello world") 
     .doOnNext(System.out::println) 
     .ignoreElements(); 
Observable<Integer> integerObservable = Observable.just(1, 2, 3, 4, 5, 6) 
     .doOnNext(System.out::println) 
     .ignoreElements(); 

Observable.merge(stringObservable, integerObservable) 
     .subscribe(new Subscriber<Object>() { 
      @Override 
      public void onCompleted() { 
       System.out.println("Finished!"); 
      } 

      @Override 
      public void onError(Throwable throwable) { 
       /*optionally handle if one of the observables calls onError()*/ 
      } 

      @Override 
      public void onNext(Object o) { /*not called*/ } 
     }); 
+0

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

+0

@Strayer добавил новое решение – AndroidEx

+0

Во время работы над этим вчера, я фактически имел более или менее ту же идею, основываясь на вашем предыдущем ответе. Спасибо за помощь! – Strayer

0

Думаю, вам нужен TaskCoordinator. Храните простой счетчик в taskCoordinator. Каждый раз, когда вы сигнализируете об успехе, счетчик будет уменьшаться. Когда счетчик достигнет нуля, обратный вызов будет выполнен. Вы можете увидеть мою реализацию следующим образом: https://github.com/codefacts/crm-common/blob/master/src/main/java/io/crm/util/TaskCoordinator.java

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

Смежные вопросы