Какова цель doOnNext(...) в RxJava

Когда мы должны использовать doOnNext() из Observable вместо onNext()?

3 ответа

Решение

doOnNext для побочных эффектов: вы хотите реагировать (например, журнал) на выбросы элемента на промежуточном этапе вашего потока, например, до фильтрации потока, для поперечного поведения, такого как регистрация, но вы все еще хотите, чтобы значение распространялось вниз по поток.

onNext более окончательный, он потребляет значение.

Прежде всего doOnNext() может вызываться еще больше раз в цепочке операторов между Observable и Subscribe, это дает вам больше возможностей для отладки вашего кода. Из-за своей "потоковой" природы отладку в RXJava нелегко doOnNext() вместо этого сделайте отладку проще. Для этой цели вы можете также рассмотреть возможность объединения его сdoOnError() оператор. Почему бы не использовать простой onNext()? Поскольку отладка не связана строго с логикой кода, теоретически вы также можете устранить doOnNext() прежде чем идти в производство.

Другая возможность его использования возникает, когда вы хотите кэшировать ответ от сервера, например, вы можете использовать map() но также doOnNext(), потому что это позволяет вам сделать ваш код более читабельным, а вместо этого вы бы поместили простой onNext() в идеале это можно было бы структурировать, чтобы следовать другим инструкциям. (Это спорно, как и все архитектурные мысли)

Типичный пример, где я нашел этот оператор, используемый в RXJava2, - показать индикатор выполнения, особенно когда вы подписываетесь на Observer без использования всех трех известных методов (onNext,onError,onComplete) аналогично случаю подписки с Consumer в RXJava2, как указано в этом фрагменте из этого подраздела блога: Показать индикатор выполнения с помощью doOnNext (<-пожалуйста, нажмите на эту ссылку, поскольку это длинный урок, перейдите непосредственно к половине страницы, чтобы увидеть, как используется 'doOnNext', в любом случае здесь следует небольшой легкий фрагмент):

@Override
protected void onStart() {
super.onStart();
Observable<String> searchTextObservable = createButtonClickObservable();

searchTextObservable

  .observeOn(AndroidSchedulers.mainThread())

  //HERE IT IS
  .doOnNext(new Consumer<String>() {
    @Override
    public void accept(String s) {
      showProgressBar();
    }
  })
  .observeOn(Schedulers.io())
  .map(new Function<String, List<String>>() {
    @Override
    public List<String> apply(String query) {
      return mCheeseSearchEngine.search(query);
    }
  })
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Consumer<List<String>>() {
    @Override
    public void accept(List<String> result) {

      hideProgressBar();
      showResult(result);
    }
  });

Равно doOnNext() и для тех же целей отладки вы можете использовать другие очевидные операторы:

doOnSubscribe (), doOnUnsubscribe (), doOnCompleted (), doOnError (), doOnTerminate (), finallyDo (), doOnEach (), doOnRequest ()

РЕДАКТИРОВАТЬ (из-за вопроса в комментариях):

doOnNext() и метод выше просто обратные вызовы, пожалуйста, обратитесь к этому, doOnNext() как говорится в официальной документации

просто изменяет Observable, чтобы он вызывал действие при вызове onNext.

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

Если вам действительно любопытно изнутри, то методы doSomethingReactive просто вызывают метод call() (обратный вызов из интерфейса действий) внутри "реального" метода SomethingReactive

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

doOnError не обрабатывает ошибку в том смысле, что не потребляет ее. Он просто что-то с ним делает, например, записывает. (То же самое верно и для doOnNext — он также не потребляет элемент, и элемент по-прежнему попадает в подписчик onNext).

      
Observable.just("Some data...")
                .doOnNext(System.out::println)
                .doOnNext(value -> System.out.println("before transform: " + value+" You can add something here but it dont affect in data"))
                .map(value -> value + "| adding some new data")
                .doOnNext(value -> System.out.println("after transform: " + value))
                .subscribe(onNext -> {
            System.out.println("onNext: "+onNext); // print out the remaining numbers
        });

Результат:

Некоторые данные...

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

после преобразования: некоторые данные...| добавление новых данных

onNext: Некоторые данные...| добавление новых данных

Другие вопросы по тегам