Оператор устранения дребезга RxJava показывает только последнюю эмиссию на Android

Я пытаюсь использовать RxJava на Android, чтобы выдать число через 1 секунду.

Однако выдается только последний элемент (7).

Что я делаю не так?

private Observable<Integer> getIntegerObservable(){
    return Observable.just(1,2,3,4,5,6,7);
}

getIntegerObservable()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .debounce(1, TimeUnit.SECONDS)
                    .subscribe(new Observer<Integer>() {
                        @Override
                        public void onSubscribe(Disposable d) {

                        }

                        @Override
                        public void onNext(Integer integer) {
                            textView.setText(textView.getText().toString() + String.valueOf(integer)+"\n");
                        }

                        @Override
                        public void onError(Throwable e) {
                            System.out.println(e.getMessage());
                        }

                        @Override
                        public void onComplete() {

                        }
                    });

person Cojoc    schedule 25.08.2018    source источник


Ответы (2)


Оператор Debounce отфильтровывает элементы, испускаемые исходным Observable, за которыми быстро следует другой испускаемый элемент.

В вашем случае числа от 1 до 7 испускаются в течение секунды. Окно, указанное для устранения дребезга, составляет одну секунду. Последний элемент, испускаемый в конце одной секунды, равен 7, поэтому все остальные элементы отфильтровываются, и вы получаете 7 в качестве вывода.

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

На следующем изображении показан другой случай, когда 6-й элемент генерируется после одного таймфрейма, поэтому и 5-й, и 6-й элементы испускаются, а остальные фильтруются. введите здесь описание изображения

Надеюсь, это поможет, попробуйте поиграть с мраморной диаграммой на сайте документации.

person Jitendra A    schedule 25.08.2018

Как сказано в документации

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

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

Я предполагаю, что вы ищете Задержка

Оператор Delay изменяет свой исходный Observable, делая паузу на определенное приращение времени (указанное вами) перед отправкой каждого из элементов исходного Observable. Это приводит к смещению всей последовательности элементов, испускаемых Observable, вперед во времени на указанное приращение.

Вместо этого он должен выглядеть примерно так:

getIntegerObservable()
          .delay(1, TimeUnit.SECONDS)
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe(...);

Вы также должны рассмотреть возможность вызова delay(..) перед subscribeOn(..), чтобы избежать блокировки основного потока.

Ознакомьтесь с этой статьей, в ней объясняется разница между subscribeOn и observeOn

ОБНОВЛЕНИЕ

Вы можете обернуть CountDownTimer в Observable. Например:

Observable.create(emitter -> new CountDownTimer(7000, 1000) {

          public void onTick(long millisUntilFinished) {
                 emitter.onNext(millisUntilFinished / 1000);
           }

           public void onFinish() {
                emitter.onComplete();
           }
         }.start())
.doOnNext() //you can log your timer here
.subscribe(); //or here

БОНУС (просто для удовольствия :D)

RxJava выглядит круче с java8

Observable.create(this::startCountDownTimer)
       .doOnNext() //use long value
       .map(String::valueOf) //map to string
       .doOnNext() //use string value
       .doOnComplete() //gets called when the timer is up
       .subscribe(this::handleTick, this::handleError);

Метод обратного отсчета

private void startCountDownTimer(ObservableEmitter<Long> emitter) {
    new CountDownTimer(7000, 1000) {
        public void onTick(long millisUntilFinished) {
            emitter.onNext(millisUntilFinished / 1000);
        }

        public void onFinish() {
            emitter.onComplete();
        }
    }.start();
}

Обработка тикающего метода

private void handleTick(String timer) {
    //Update UI
}

Метод обработки ошибок

private void handleError(Throwable t) {
    //Log and inform user
}
person Muhammad Youssef    schedule 25.08.2018
comment
Это не работает так, как я хочу, он ждет этого временного интервала, а затем испускает все сразу - person Cojoc; 26.08.2018