RxJava, хороший пример использования flatmap



Я новичок в RxJava, часто путаюсь в функции flatMap. Согласно doc, flatmap transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable



Может ли кто - нибудь привести хороший пример его использования? Зачем превращать исходное наблюдаемое в наблюдаемое (множественное число), а затем превращать их в единое наблюдаемое?



Почему бы вам просто не использовать "карту"?



Если вы приведете пример в Android, это потрясающе, в противном случае достаточно простой Java. Спасибо

562   3  

3 ответов:

Допустим, у вас есть

Observable<Foo> fooObservable;

И вы хотите вызвать другой метод, который принимает Foo и выдает Observable<Bar>

Что-то вроде:

public Observable<Bar> getBars(Foo foo);

Если вы это сделали:

fooObservable.map(foo -> getBars(foo));

Вы закончите с Observable<Observable<Bar>>, потому что вы трансформировали свой Foo -> Observable<Bar> а это, вероятно, не то, чего ты хочешь.

Вместо этого вы можете использовать flatMap, который "сглаживает наблюдаемое":

Observable<Bar> barObservable = fooObservable.flatMap(foo -> getBars(foo));

Я вижу тег Android на вашем вопросе. Так что, вероятно, вы должны быть знакомы с Retrofit.

Давайте представим, что у вас есть 2 метода:

public interface FoxreyRestApi {

    @POST("/signin")
    Observable<SignInResponse> signin(@Body SignInRequest request);

    @GET("/user")
    Observable<User> getUser(String accessToken);
}

Вы хотите получить пользовательские данные, но вам нужно accessToken, которое возвращает SignInResponse.

Вы можете сделать это:

1). Создайте свой RestAdapter.

2). Выполняйте запросы один за другим:

restAdapter.signin(request)
    .flatMap(r -> restAdapter.getUser(r.getAccessToken()))
    .subscribe(user -> {/*User your user*/});

Очень часто я использую его для преобразования некоторых событий пользовательского интерфейса в наблюдаемые фоновые задачи:

ViewObservable.clicks(calculateBtn)
    .flatMap(new Func1<OnClickEvent, Observable<Integer>>() {
      @Override
      public Observable<Integer> call(OnClickEvent onClickEvent) {
          return observeBackgroundOperation()
            .observeOn(AndroidSchedulers.mainThread())//interaction with UI must be performed on main thread
            .doOnError(new Action1<Throwable>() {//handle error before it will be suppressed
                @Override
                public void call(Throwable throwable) {
                    progress.setVisibility(View.GONE);
                    calculateBtn.setEnabled(true);
                    Toast.makeText(IOCombineSampleActivity.this, R.string.mix_error_message, Toast.LENGTH_SHORT).show();
                }
            })
            .onErrorResumeNext(Observable.<Integer>empty());//prevent observable from breaking
      }
    })
    .subscribe(new Action1<Integer>() {...});

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

Заметим, что наблюдаемое в flatMap может выдавать единичное значение, что и делается в выборке.

Таким образом, я декларативно определил взаимодействие между пользовательским интерфейсом и фоновыми процессами. Я обрабатываю ошибки с помощью doOnError , а затем использую onErrorResumeNext(Observable.<Integer>empty()), чтобы предотвратить завершение observable с помощью onError. Поскольку я использую flatMap, мой observable не завершен (в то время как внутренний flatMap был) и ждет событий следующего щелчка.

Полный образец кода Вы можете найти в моей статье.

Comments

    Ничего не найдено.