I have 2 functions, I need the first one to be completed first and then the second, but running it on one thread took a long time so I tried running it like with CoroutineScope, but the second function executes even if not all images are downloaded.
downloadSkillsImages(context)
addSkillsToDB()
private suspend fun downloadSkillsImages(context: Context) {
for (i in 0 until skills.size) {
CoroutineScope(IO).launch {
try {
val url = fbStorage.reference.child("skillImagesMini").child("${skills[i].skillId}.jpg").downloadUrl.await()
skills[i].skillImage = getBitmapFromUri(url, context)
}catch (e: Exception){
//image not found, nothing happens
}
}
}
}
CodePudding user response:
This is what the coroutineScope
scope function is for. It waits for all its children coroutines to finish.
private suspend fun downloadSkillsImages(context: Context) = coroutineScope {
for (i in skills.indices) {
launch(Dispatchers.IO) {
try {
val url = fbStorage.reference.child("skillImagesMini").child("${skills[i].skillId}.jpg").downloadUrl.await()
skills[i].skillImage = getBitmapFromUri(url, context)
} catch (e: Exception){
//image not found, nothing happens
}
}
}
}
Note, you only need to specify Dispatchers.IO if getBitmapFromUri
is a blocking function. If it's a suspend function, then nothing in this child coroutine is blocking, so it wouldn't matter what dispatcher is used to call it.
Since you want your coroutines to all finish and silently ignore the ones that fail, you can simplify this by using supervisorScope
instead of coroutineScope
so you don't need try/catch. supervisorScope
will complete successfully even if some of its children fail.
private suspend fun downloadSkillsImages(context: Context) = supervisorScope {
for (i in skills.indices) {
launch(Dispatchers.IO) {
val url = fbStorage.reference.child("skillImagesMini").child("${skills[i].skillId}.jpg").downloadUrl.await()
skills[i].skillImage = getBitmapFromUri(url, context)
}
}
}