The Monster
09/08/2021, 7:52 PMreturn webservice.getAllFacts()
.also {
coroutineScope {
launch {
catFactDao.insertAllFacts(it)
}
}
}
Code compiles, but is it a bad idea to use scope function on the return value (does it block even with the coroutine?)val list: List<CatFact> = webservice.getAllFacts()
coroutineScope {
launch {
catFactDao.insertAllFacts(list)
}
}
return list
suspend
function must be stopped when that function returns
https://developer.android.com/kotlin/coroutines/coroutines-adv#parallelJoffrey
09/08/2021, 10:49 PMcoroutineScope { launch { suspendCall() }}
is equivalent to just suspendCall()
, because coroutineScope
waits for its child coroutines to finish before returningThe Monster
09/08/2021, 11:26 PMlist
while leaving the IO task (insert the list into DB
) running by itself. The coroutine techniques I tried, like Dispatchers.IO for example, are still blocking the method from returning. the only way that worked was to create a new Thread.
suspend fun getAllFacts(): List<CatFact> { //TODO return Flow<List<CatFact>> instead
if (allFactsLoaded) {
return catFactDao.selectAllFacts()
} else {
val list: List<CatFact> = webservice.getAllFacts()
//thread(start = true) {
// catFactDao.insertAllFacts(list)
//}
catFactDao.insertAllFacts(list)
return list
}
}
I am still reading the coroutines docs to see if there is anything else I can try.Joffrey
09/08/2021, 11:32 PMgetAllFacts
either as argument or more conventionally as receiver (although we're already breaking conventions anyway 😄 ).
So your function could look like this:
suspend fun CoroutineScope.getAllFacts(): List<CatFact> {
if (allFactsLoaded) {
return catFactDao.selectAllFacts()
} else {
val list: List<CatFact> = webservice.getAllFacts()
launch {
catFactDao.insertAllFacts(list)
}
return list
}
}
You could also just have the scope somewhere in the class that declares this function, and simply use it to launch the coroutine:
suspend fun getAllFacts(): List<CatFact> {
if (allFactsLoaded) {
return catFactDao.selectAllFacts()
} else {
val list: List<CatFact> = webservice.getAllFacts()
someScope.launch {
catFactDao.insertAllFacts(list)
}
return list
}
}
The Monster
09/09/2021, 12:13 AMcoroutineScope { launch { suspendCall() }}
is useless because there is no non-returning code outside of the coroutineScope
AND there is only one launch
call? I swear I saw code written like this in the docs, but now I read it again, the call outside of the coroutineScope
is a println()
lol.Joffrey
09/09/2021, 12:19 AMcoroutineScope
suspends until all child coroutines are done, but if there is just one and no code running concurrently with it (inside coroutineScope
), there is no point. It's like doing async { suspendCall() }.await()
- starting a coroutine and immediately waiting for itcoroutineScope {
launch { suspendCall() }
somethingElse()
}
is ok because suspendCall
and somethingElse
will run concurrentlyThe Monster
09/09/2021, 12:21 AMprivate val scope: CoroutineScope = CoroutineScope(EmptyCoroutineContext)
I am glad that you said using the outer coroutine breaks convention, which aligns with the Android docs from Google. I will take some more time to process your statements because I am quite a beginner in coroutines.Joffrey
09/09/2021, 12:29 AM