Поток, который периодически выдает последнее значение, и когда приходит новое значение

#kotlin #kotlin-coroutines

Вопрос:

Я хочу создать сопрограммы Kotlin Flow , которые будут выдавать значения, когда

  1. они меняются, и
  2. периодически выдает последнее доступное значение, каждые x секунд с момента последнего изменения или последнего выброса.

Ответ №1:

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

 flow.transformLatest { value ->
  while(currentCoroutineContext().isActive) {
    emit(value)
    delay(x)
  }
}
 

Комментарии:

1. Вы можете отказаться от isActive чека. Отмена будет работать так же.

2. Верно, но while петли без условий меня раздражают. Мне нравится дополнительная часть ума, которую обеспечивает явная проверка.

Ответ №2:

Вы можете создать Flow устройство, которое излучает через регулярные промежутки времени, а затем просто использовать combine . Каждый раз, когда вы объединяете значения, вы на самом деле просто передаете текущее значение Flow интересующего вас оригинала.

     // This is the main flow you are interested in. This uses
    // a Flow builder just as a simple example but this could
    // be any kind of Flow, like a (Mutable)StateFlow.
    val emitter = flow {
        emit("Your data")
        // ...
    }
    // This just serves as a timer.
    val timer = flow {
        while (currentCoroutineContext().isActive) {
            emit(Unit)
            delay(500)
        }
    }
    // This will emit whenever either of the Flows emits and 
    // continues to do so until "emitter" stops emitting.
    combine(
        emitter,
        timer
    ) {  value, ticker ->
        // Always just return the value of your
        // main Flow.
        value
    }
 

Комментарии:

1. Это прекратится, когда закончится последний выброс

2. @ShawnThye уверен, но это предполагает, что есть последний «выброс». Я использовал здесь построитель потоков только для того, чтобы иметь самодостаточный пример, но, по-видимому, мы говорим о том, чтобы начать с другого потока, который никогда не «заканчивается». И если они начинают с потока, который действительно заканчивается, возможно, они хотели бы, чтобы общий поток тоже закончился. Но все сводится к тому, что они ищут. Я лично уже в настоящее время использую это решение при объединении потока «тикера», как я предложил, с потоком MutableStateFlow.

3. Да, я думаю, что в его случае ему нужно использовать MutableShareFlow или MutableStateFlow в зависимости от его области применения 🙂