RxJava - 将 delaySubscription 与 withLatestFrom 一起使用

RxJava - using delaySubscription with withLatestFrom together

很难解释我的问题,这就是为什么我会尝试用一个更简单的例子来解释。 (我也会在括号中包含我的案例,以明确为什么我需要解决这个问题)

    val interval =
        Observable.interval(1, TimeUnit.SECONDS)

    val delayedRandomNumber =
        Observable.fromCallable {
            val randomNumber = Random().nextInt()
            Log.d("LogTag", "random number = $randomNumber")
            randomNumber
        }.delay(5000, TimeUnit.MILLISECONDS)

    interval
        .observeOn(Schedulers.io())
        .filter { it != 0L }
        .delaySubscription<Int>(delayedRandomNumber)
        .withLatestFrom(delayedRandomNumber, BiFunction<Long, Int, String> { second, randomNumber ->
            "$randomNumber mod $second = ${randomNumber%second}"
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe {
            Log.d("LogTag", it)
        }

interval - 很明显,这每秒都会发出值(在我的例子中,它是从 EditText 发出的用户输入)

delayedRandomNumber - 这会生成一个随机数并在 5 秒后发出。我只需要生成一次但现在我不知道如何生成(在我的例子中它是来自服务器的 json 城市树)

delaySubscription - 我正在使用此运算符等待随机数。如果我不使用它,我将不会获得第二个值 1、2、3 的值(在我的例子中,我需要从第一个字母开始,因为它是基于树的数据——我有这样的约束)

withLatestFrom - 我使用这个运算符来避免每次都生成随机数(在我的例子中,我不想每次输入改变时都从服务器获取数据)

所以我需要同时使用delaySubscriptionwithLatestFrom。但是它通过生成随机数两次(在我的例子中加载数据两次)来制造问题

当我运行这段代码时,日志看起来是这样的:

random number = -1870536123
random number = -1834197628
-1870536123 mod 1 = 0
-1870536123 mod 2 = -1
-1870536123 mod 3 = 0
-1870536123 mod 4 = -3
-1870536123 mod 5 = -3
-1870536123 mod 6 = -3

如您所见,随机数生成了两次。

还有其他方法可以解决这个问题吗?如果是怎么办?

因为delayedRandomNumbercold observable或者单播。每个订阅都有自己的生产者(在您的情况下 Observable.fromCallable 内的随机数生成是生产者)。

为避免此问题,您可以使用 share 运算符多播 delayedRandomNumber

    val delayedRandomNumber =
        Observable.fromCallable {
            val randomNumber = Random().nextInt()
            Log.d("LogTag", "random number = $randomNumber")
            randomNumber
        }.delay(5000, TimeUnit.MILLISECONDS)
         .share()

输出

random number = -942235082
result=-942235082
-942235082 mod 1 = 0
result=-942235082
-942235082 mod 2 = 0
result=-942235082
-942235082 mod 3 = -2

也请阅读 blog by Dan Lew,因为我发现它在遇到多播可观察对象问题时很有帮助。