Как не прерывая Flow вызвать долгую по времени выполнения suspend функцию?
Я пытаюсь разобраться в принципах работы с Kotlin Coroutines. У меня есть список передаваемый через Flow в Viewmodel.
val chatsFlow = chatsChangedFlow.asSharedFlow()
.map {
chatList.map { chat ->
Chat(
id = chat.id,
title = chat.title,
photo = chat.photo?.let {
val photoFilePath = downloadFile(it.file)
ProfilePhoto(
thumbnail = it.thumbnail.data,
filePath = photoFilePath
)
}
)
}
}
И каждый раз при вызове downloadFile Flow дожидается возврата значения, лишь после этого идёт на следующую итерацию.
Можно ли добиться в данном случае поведения чтоб при вызове downloadFile поле filePath оставалось неинициализированным и лишь после обработки значения через некоторое время заполнялось тем самым не прерывая работы Flow?
P.S. downloadFile тоже suspend функция на основе suspendCancellableCoroutine
Ответы (1 шт):
И каждый раз при вызове downloadFile Flow дожидается возврата значения, лишь после этого идёт на следующую итерацию.
Да и это нормально. Ситуация, когда "скорость обработки значений ниже, чем скорость эмитирования новых данных" корректируется через Стратегии переполнения буфера через метод .buffer()
но что-то подсказывает, что вам это не поможет. вы лишь упустите часть новых данных.
при вызове downloadFile поле filePath оставалось неинициализированным и лишь после обработки значения
для этого в корутинах можно запускать дочерние корутины launch или async
async возвращает тип Deffered - это нейкая работа, результат который вы можете долждаться и получить вызвав на ней .await()
возможно стоить сделать filePath именно типа Deffered<String>, но это не точно.
UPD
отбой =(
внутри .map нельзя вызвать async и из suspend функций нельзя вернуть незаконченные Deferred
UPD 2.0
именно, что из suspend нельзя, но никто не мешает сделать обычный метод, который будет возвращать Deferred!
fun downloadFile() : Deferred<String> = viewModelScope.async {
delay(3000)
"hello world"
}