Я бы хотел, конечно, чтобы сразу начать обработку текущего потока, но «придерживать» результат до тех пор, пока не пройдет это время.
Мне это нужно в приложении для Android, которое я сейчас пишу, потому что, если что-то будет загружается достаточно быстро, поток завершится во время перехода входа NavHost, что приведет к зависанию.
Конечно, альтернативой было бы немедленно запустить запрос (не HTTP, извините) и ожидаю завершения перехода, но боюсь, что решение будет похоже на это (за исключением того, что поток «ожидания» будет отличаться от задержки).
Я узнал о потоке zip, потому что там написано:
Значения из текущего потока (this) сжимаются с другим потоком, используя предоставленную функцию преобразования. применяется к каждой паре значений. Результирующий поток завершается, как только завершается один из потоков, и в оставшемся потоке вызывается метод отмены.
И вот пример:
Код: Выделить всё
val flow = flowOf(1, 2, 3).onEach { delay(10) }
val flow2 = flowOf("a", "b", "c", "d").onEach { delay(15) }
flow.zip(flow2) { i, s -> i.toString() + s }.collect {
println(it) // Will print "1a 2b 3c"
}
Последняя фраза — это то, что я вижу в мой код.
Поток «ожидания» не отменяется автоматически после завершения zip.
Поскольку я также перезапускаю этот поток при обновлении по запросу, в следующий раз, когда он зависнет (не произойти без этой задержкиResultAtMost).
Это мой код, и из LogCat я могу видеть только:
СТАРТ
ЗАДЕРЖКА: L: 252
но я не вижу «КОНЕЦ»...
Код: Выделить всё
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.zip
import kotlin.time.Duration
/**
* Waits [d] to produce a result if the result of the current flow is ready before [d].
* For example, if [d] is 5 seconds and the result of the current flow is ready at `t = 2 seconds`,
* this "modifier" will wait another 3 seconds before returning the result.
*
* If, instead, the result is ready at `t = 7 seconds`, return it when it's ready.
*
* @param d the minimum time to wait for the result.
*/
fun Flow.delayResultAtMost(d: Duration): Flow {
val waitFlows = flow {
val ctx = currentCoroutineContext()
Log.d("FLOW", "START")
val start = System.currentTimeMillis()
delay(d)
val end = System.currentTimeMillis()
val delta = end - start
Log.d("FLOW", "DELAY: L: $delta")
while(ctx.isActive) {
emit(Unit)
}
Log.d("FLOW", "END")
}
return this.zip(waitFlows) { a, _ -> a }
}
Или этот подход совершенно неправильный? (Кстати, возможно, это потому, что я впервые использую Kotlin Flow и Jetpack Compose).
Подробнее здесь: https://stackoverflow.com/questions/790 ... n-amount-o