RxJava - использование delaySubscription с withLatestFrom вместе - PullRequest
0 голосов
/ 22 сентября 2019

Трудно объяснить мою проблему, поэтому я постараюсь объяснить на более простом примере.(Я также включу свой случай в скобки, чтобы пояснить, почему мне нужно решить эту проблему)

    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)
        }

интервал - очевидно, что это генерирует значение каждую секунду (в моем случаеэто пользовательский ввод из EditText)

delayedRandomNumber - генерирует случайное число и выдает его через 5 секунд.Мне нужно сгенерировать только один раз, но сейчас я не знаю, как (в моем случае это дерево городов json с сервера)

delaySubscription - я использую этот оператор для ожиданияслучайное число.Если я не использую это, я не получу значение для вторых значений 1,2,3 (в моем случае мне нужно начинать с первой буквы, потому что это данные на основе дерева - у меня есть такое ограничение)

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

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

Когда я запускаю этот код, журнал выглядит так:

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

Как вы можете видеть случайное числочисло генерируется дважды.

Есть ли другой способ решить эту проблему?Если да, то как?

1 Ответ

2 голосов
/ 22 сентября 2019

Это потому, что delayedRandomNumber является наблюдаемым в холодном состоянии или одноадресным.Каждая подписка будет иметь своего собственного производителя (в вашем случае генерация случайных чисел внутри Observable.fromCallable является производителем).

Чтобы избежать этой проблемы, вы можете выполнить многоадресную рассылку delayedRandomNumber с помощью оператора share .

    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

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

...