【问题标题】:rxJava debounce() operator not working with Observable.range()rxJava debounce() 运算符不适用于 Observable.range()
【发布时间】:2017-12-09 15:38:32
【问题描述】:

AFAIK,rxJava 的debounce() 运算符用于延迟事件的发射。当我使用搜索框应用它时,它可以正常工作:

RxTextView.textChangeEvents(editText)
                .debounce(1000, TimeUnit.MILLISECONDS) //Only emit after 1 sec
                .subscribe(new Observer<TextViewTextChangeEvent>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(TextViewTextChangeEvent event) {
                        //Get more information about text change event
                        Log.e(TAG, "Before: " + event.before() + ", start: " + event.start() + ", count: " + event.count());
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        Log.e(TAG, "textChangeEvents: onComplete");
                    }
                });

但是当我像这样使用Observable.range() 应用它时:

Observable.range(1, 10000)
                .debounce(1000, TimeUnit.MILLISECONDS)
                .subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull Long integer) {

                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

尽管我已经应用了debounce(1000, TimeUnit.MILISECONDS) 操作符,但排放量会以非常快的速度(大约 1000 个排放量/秒)持续达到onNext()

我期望的是:当我使用debounce() 时,延迟 1000 毫秒后只会发出 1 个数字(它可以在延迟 2 次发射之间跳过数字)。意味着发射将像上面的搜索框示例一样向下游移动。

我是 rx 新手,请帮助我实现这一目标并解释原因?我真的不知道为什么我必须使用另一个运算符,但 debounce() 因为这个想法是一样的!

【问题讨论】:

  • debounce 通过定义一个宽限期来防止下游不堪重负,该宽限期必须在事件之间经过才能获得最后一个事件。 Range 将尽可能快地检查其项目。 2.x 的扩展项目为此使用了 spanout 运算符。
  • @akarnokd 我没明白,为什么不能以同样的方式应用它们,而是使用 spanout?
  • 不同的运算符用于不同的目的、转换和协调模式。
  • @akarnokd,先生,据我了解,只应发出最后一个值(10000),因为这些项目“尽可能快”发出,因此每次重置 1000 毫秒计数器,并且只有当最后一个项目(10000)被发出时,1000ms 才会最终失效。这不是debounce()应该如何运作吗?
  • @azizbekian 当我在Android主线程上观察它时它只会发出最后一个值(10000)(导致应用程序没有响应)

标签: java android rx-java rx-android rx-java2


【解决方案1】:

debounce 通过定义一个宽限期来防止下游不堪重负,该宽限期必须在事件之间经过才能获得最后一个事件,换句话说,它将在一段时间后发出最新的元素。 Range 将尽可能快地通过它的项目,因此项目之间没有足够的时间,只会发出最后一个。

debounce 根本不是您的用例所需的运算符。 2.x 的扩展项目为您的用例提供了 spanout 运算符。

【讨论】:

    【解决方案2】:

    您需要的是每个项目的'.delay()' 运算符。请参阅此处的说明 - http://reactivex.io/RxJava/javadoc/rx/Observable.html#delay-rx.functions.Func1-

    Observable
        .range(1, 10000)
        .delay(new Func1<Integer, Observable<Long>>() {
            @Override
                public Observable<Long> call(Integer integer) {
                    return Observable.timer(1, TimeUnit.SECONDS );
                }
        });
    

    为了良好的秩序,'.debounce()' 对于这个用例来说绝对是不可能的。

    【讨论】:

    • 但是,为什么我不能使用debounce? 2个用例有什么区别?
    • 因为 debounce 通过跳过而不是延迟来防止事件频繁出现
    • 我知道去抖动跳过项目。但是当我增加要发射的项目数量时,比如range(1, 1000000000),然后我使用debounce 500 毫秒。我认为 1000000000 会在比 500 毫秒更长的时间内发出,但它仍然只发出最后一项。
    • 只有事件之间的时间间隔很重要。显然在你的情况下,他们设法在他们之间有更大的间隔。如果添加另一个调度程序作为 debounce 的第三个参数,它的行为是否相同?
    【解决方案3】:

    使用延迟而不是去抖动

    Observable.range(1, 10000)
              .delay(1000, TimeUnit.MILLISECONDS)
              .subscribe(...);
    

    【讨论】:

    • 但是,为什么我不能使用debounce?有什么区别?
    • @nhoxbypass debounce 会丢弃值,如果它们被过于频繁地发出,在你的情况下,所有值几乎同时发出,所以 debounce 会丢弃除 1 之外的所有值
    • 延迟会在每个值后暂停
    • 发射range(1, 1000000000) 真的很快,不到500ms
    【解决方案4】:
      Observable.range(1, 10000)
                .debounce(500, TimeUnit.MILLISECONDS)
                // Run on a background thread
                .subscribeOn(Schedulers.io())
                // Be notified on the main thread
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(....);
    

    试试这个方法。

    【讨论】:

      猜你喜欢
      • 2018-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多