【问题标题】:How to chain observables with different intervals in RxJava?如何在 RxJava 中以不同的间隔链接 observables?
【发布时间】:2018-10-16 12:03:00
【问题描述】:

我看到很多关于让Rx 延迟事件的每次发射的帖子:How to make countdown timer with RxJS Observables?How to use RxJava Interval OperatorAdding delay between Observable Items RxJavaRxJava delay for each item of list emitted 等。

不过,我没有看到任何具有不同延迟的链接。

基本上,我有一个 Textview 和一个字母列表,我想:

  • 将文本设置为第一个字母
  • 等待 1500 毫秒
  • 将文本设置为空
  • 等待 500 毫秒
  • 将文本设置为第二个字母
  • 等待 1500 毫秒
  • 将文本设置为空
  • 等待 500 毫秒
  • 重复整个列表

代码实现可能看起来像这样(但我猜doThing()Rx 中是无稽之谈,而delay() 不是为了这个):

Observable.fromArray(new String[]{"A", "B", "C", "D", "E"})
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .delay(500L, TimeUnit.MILLISECONDS)
        .doThing((String i) -> {
            textView.setText("");
            Log.d("XXX", "MainActivity :: onCreate (110): letter="+ i);
        })
        .delay(1500L, TimeUnit.MILLISECONDS)
        .doThing((String i) -> {
            textView.setText(i);
            Log.d("XXX", "MainActivity :: onCreate (110): letter="+ i);
        });

如何使用 Rx 实现这一点?

编辑:我可以将rxjava delay: How to get variable delay on each item emitted from a list? 的答案与字母列表一起使用,其中一个字母对两个是特殊的(可能是空?),但它似乎过于复杂。

【问题讨论】:

  • 您可以尝试使用 zip 或 concat map。基本上你有两个 observables,一个用于数据,一个用于延迟(交替 500/1500 延迟)。然后你把它们结合在一起。 (是的,这是你最后一个链接的答案)
  • @AngelKoh 你的意思是我在编辑或介绍中的最后一个链接?如果在我的编辑中,我认为这样一个常见的任务可以以一种不那么乏味的方式完成。如果在我的介绍中,你能提供一个小例子作为答案吗?这对我有很大帮助!

标签: android rx-java delay reactivex


【解决方案1】:

序列A (1500ms) null (500ms) B (1500ms) null (500ms) C (500ms) null (1500ms)

textAnimationDisposable = Observable.fromArray("A", "B", "C")
        .concatMap(string ->
              Observable.merge(
                 Observable.just(string),
                 Observable.just("").delay(1500, TimeUnit.MILLISECONDS)
              )
              .concatWith(Observable.<String>empty().delay(500, TimeUnit.MILLISECONDS))
        )
        .observeOn(AndroidSchedulers.mainThread())
        .subscribeOn(Schedulers.newThread())
        .subscribe(string -> textView.setText(string));

您链接的last solution 对于单独控制每个项目的延迟非常有用。

【讨论】:

  • 这看起来很有希望,谢谢!我澄清了我的序列,它对应于您的第二个代码。不幸的是,您的代码不起作用:照原样,我得到一个ViewRootImpl$CalledFromWrongThreadException,在concatMap() 中还有更多.observeOn(AndroidSchedulers.mainThread()),我从未看到null 文本。
  • 啊,是的,concatMap() 中创建的 observable 在后台线程上运行并试图从那里更改布局。这导致了ViewRootImpl$CalledFromWrongThreadException。我在一个 android 项目中尝试过,正在更新答案...
  • 序列仍然有一个问题:空字符串出现在文本之后。在最后一项之后,textview 将为空。
  • 序列可以在完成后重新启动以消除这种情况。此外,如果string 是列表中的最后一项并且不发出空字符串,则可以在concatMap 中检查。然后最后一个字符串将留在文本视图中。
  • 太棒了,这就像一个魅力!其实我加了一个Action()作为onComplete,所以在最后一个之后,“游戏”就结束了。
猜你喜欢
  • 1970-01-01
  • 2017-01-06
  • 2019-08-13
  • 2015-03-26
  • 1970-01-01
  • 2016-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多