Home > Back-end >  Is there a way how I can run code on multiple threads so it gets executed faster and then wait for a
Is there a way how I can run code on multiple threads so it gets executed faster and then wait for a

Time:04-25

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)
        }
    }
}
  • Related