Объединение наблюдаемых в RxJava

Объединение наблюдаемых в RxJava

1. Вступление

В этом кратком руководстве мы обсудим различные способы комбинированияObservables в RxJava.

Если вы новичок в RxJava, обязательно сначала ознакомьтесь с этимintro tutorial.

А теперь приступим.

2. Observablesс

ПоследовательностиObservable, или простоObservables, представляют собой асинхронные потоки данных.

Они основаны наObserver pattern, в котором объект с именемObserver подписывается на элементы, отправленныеObservable.

Подписка не является блокирующей, посколькуObserver должен реагировать на все, чтоObservable будет излучать в будущем. Это, в свою очередь, облегчает параллелизм.

Вот простая демонстрация на RxJava:

Observable
  .from(new String[] { "John", "Doe" })
  .subscribe(name -> System.out.println("Hello " + name))

3. Объединение наблюдаемых

При программировании с использованием реактивного фреймворка обычно комбинируют различныеObservables.

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

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

В этом разделе мы обсудим некоторые из различных способов объединения несколькихObservablesв RxJava и различные варианты использования, к которым применим каждый метод.

3.1. Mergeс

Мы можем использовать операторmerge, чтобы объединить вывод несколькихObservables, чтобы они действовали как один:

@Test
public void givenTwoObservables_whenMerged_shouldEmitCombinedResults() {
    TestSubscriber testSubscriber = new TestSubscriber<>();

    Observable.merge(
      Observable.from(new String[] {"Hello", "World"}),
      Observable.from(new String[] {"I love", "RxJava"})
    ).subscribe(testSubscriber);

    testSubscriber.assertValues("Hello", "World", "I love", "RxJava");
}

3.2. MergeDelayErrorс

МетодmergeDelayError аналогичен методуmerge тем, что объединяет несколькоObservables в один, ноif errors occur during the merge, it allows error-free items to continue before propagating the errors:

@Test
public void givenMutipleObservablesOneThrows_whenMerged_thenCombineBeforePropagatingError() {
    TestSubscriber testSubscriber = new TestSubscriber<>();

    Observable.mergeDelayError(
      Observable.from(new String[] { "hello", "world" }),
      Observable.error(new RuntimeException("Some exception")),
      Observable.from(new String[] { "rxjava" })
    ).subscribe(testSubscriber);

    testSubscriber.assertValues("hello", "world", "rxjava");
    testSubscriber.assertError(RuntimeException.class);
}

Пример вышеemits all the error-free values:

hello
world
rxjava

Обратите внимание, что если мы используемmerge вместоmergeDelayError,String «rxjava” не будет выдан, потому чтоmerge немедленно останавливает поток данных отObservables при возникновении ошибки.

3.3. Zipс

Метод расширенияzipbrings together two sequences of values as pairs:

@Test
public void givenTwoObservables_whenZipped_thenReturnCombinedResults() {
    List zippedStrings = new ArrayList<>();

    Observable.zip(
      Observable.from(new String[] { "Simple", "Moderate", "Complex" }),
      Observable.from(new String[] { "Solutions", "Success", "Hierarchy"}),
      (str1, str2) -> str1 + " " + str2).subscribe(zippedStrings::add);

    assertThat(zippedStrings).isNotEmpty();
    assertThat(zippedStrings.size()).isEqualTo(3);
    assertThat(zippedStrings).contains("Simple Solutions", "Moderate Success", "Complex Hierarchy");
}

3.4. Почтовый индекс с интервалом

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

@Test
public void givenAStream_whenZippedWithInterval_shouldDelayStreamEmmission() {
    TestSubscriber testSubscriber = new TestSubscriber<>();

    Observable data = Observable.just("one", "two", "three", "four", "five");
    Observable interval = Observable.interval(1L, TimeUnit.SECONDS);

    Observable
      .zip(data, interval, (strData, tick) -> String.format("[%d]=%s", tick, strData))
      .toBlocking().subscribe(testSubscriber);

    testSubscriber.assertCompleted();
    testSubscriber.assertValueCount(5);
    testSubscriber.assertValues("[0]=one", "[1]=two", "[2]=three", "[3]=four", "[4]=five");
}

4. Резюме

В этой статье мы рассмотрели несколько методов объединенияObservables с RxJava. Вы можете узнать о других методах, таких какcombineLatest,join,groupJoin,switchOnNext, вofficial RxJava documentation.

Как всегда, исходный код этой статьи доступен в нашихGitHub repo.