SharedFlow: mapLatest не запускается

Давайте сделаем это просто. У меня есть одно имя в моем.

      private val sortOrder = MutableSharedFlow<String>(
    replay = 0,
    extraBufferCapacity = 1
)

Я подключен к, чтобы обновлять данные всякий раз, когда они меняются.

      val data = sortOrder.mapLatest {
    Timber.d("Sort order changed to $it")
    "Sort order is $it"
}

У меня есть наблюдатель, слушающий data в деятельности.

      viewModel.data.asLiveData().observe(this) {
    Timber.d("onCreate: New data is $it")
}

и, наконец, я меняю ViewModelс init метод

      init {
    sortOrder.tryEmit("year")
}

но даже после изменения sortOrderзначение, не срабатывает. Есть идеи, почему?

я использую MutableSharedFlow контролировать replay свойство для предотвращения выполнения mapLatest body каждый раз, когда я поворачиваю экран (или когда действие воссоздается).

Полный исходный код

PS: Я новичок в Flow API

2 ответа

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

      val sortOrder = MutableSharedFlow<String>(
    replay = 0,
    extraBufferCapacity = 1
)

val data = sortOrder.mapLatest {
    Timber.d("Sort order changed to $it")
    "Sort order is $it"
}

sortOrder.tryEmit("year")

data.asLiveData().observe(this) {
    Timber.d("onCreate: New data is $it")
}

Решение зависит от вашего желаемого поведения:

Если вы согласны с тем же значением, которое потенциально может быть отправлено новым сборщикам, вы можете просто установить reply = 1 (а потом extraBufferCapacity можно установить на 0).

Другое решение - убедиться, что он не вызывается до тех пор, пока viewModel.data.asLiveData().observe(...)вызывается и убедитесь, что действие хотя бы в возобновленном состоянии при вызове tryEmit в противном случае значение игнорируется.

я думаю следует избегать в тех случаях, когда у вас нет повтора, но вы по-прежнему не хотите, чтобы ваши события отбрасывались.

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

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

Другие вопросы по тегам