Reputation: 2010
I have a concern regarding coroutines
. What I'd like to do is that a specific code is executed after several requests have been completed ... Before I used completionHandlers
and work correctly, the problem is that there are more requests and I don't want to nest them, I think is not the correct practice ... So I don't know if you suggest anything for this exercise. I propose the following but I am not sure if it is the best:
val job = viewLifecycleOwner.lifecycleScope.launch {
// API calls
Process1 (view)
Process2 (view)
Process3 (view)
Process4 (view)
}
runBlocking {
job.join ()
// Continue normally
}
Thanks for reading!
Ps. Each "Process" calls an API
and responds as a completionHandler
Upvotes: 0
Views: 1587
Reputation: 1368
Here is a simple example of 2 different methods of returning values from coroutines. You can not guarantee when a coroutine will return or finish, so you must either have some sort of callback function that does work with your api return data, or you can use the withContext method to work with it closer to a normal code flow. Either way, the coroutine code cant be joined back with synchronous code, and runBlocking is considered bad practice.
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class MyViews {
private val apis = Apis()
fun onViewCreate() {
// Using example of launch -- cannot return value
// This code will split off from the sync flow, and we cannot guarantee when any of it is ran, except the order it will be run in
CoroutineScope(Dispatchers.IO).launch {
// One method to elevate values out of a coroutine would be callbacks
callApisWithCallbacks { data ->
processApiData(data)
}
}
// Internally this utilizes withContext to resolve a value that is ready to be used
callApisWithReturn()
// Continue normal work flow here
}
fun processApiData(age: Int) {
// Do work here
println("Current users age: $age")
}
fun callApisWithReturn() {
// Use launch to get into coroutine from sync code
CoroutineScope(Dispatchers.Default).launch {
// withContext will return a value and can be used as if inline
val userAge = withContext(Dispatchers.IO) { apis.getUserAge() }
processApiData(userAge)
}
// Suspend function cant be called outside of coroutine
// apis.getUserAge()
}
suspend fun callApisWithCallbacks(cb: (Int) -> Unit) {
val age = apis.getUserAge()
cb(age)
}
}
class Apis {
suspend fun getUserAge(): Int {
// Simulate delay from API
delay(1000)
return 5
}
}
Upvotes: 2