Hi I am using Kotlin coroutine library in a project.
The below method calls a suspend function which return a boolean value.
fun isNetworkAvailable(context: Context?): Boolean {
//return checkNetworkReachability(context)
var isNetworkAvailable = false
GlobalScope.launch(Dispatchers.Default) {
isNetworkAvailable = GlobalScope.async<Boolean> {
checkNetwork()
}.await()
}
return isNetworkAvailable
}
Here checkNetwork is the suspend function. Before executing it the return value is passed to the caller (View/Activity). How could I achieve without making the "isNetworkAvailable" as suspend?.
Inside the checkNetwork method, to check reach-ability calling network call as like below.
private suspend fun checkNetwork() : Boolean {
val value = GlobalScope.async<Boolean> {
val isEastReachable = async { checkEastReachable() }
if (!isEastReachable.await()) {
checkWestReachable()
} else {
true
}
}
return value.await()
}
And the sub-methods are
private suspend fun checkEastReachable(): Boolean = coroutineScope {
withContext(Dispatchers.Default) {
repository.networkManager.callReachableEast()
}
}
private suspend fun checkWestReachable(): Boolean = coroutineScope {
withContext(Dispatchers.Default) {
repository.networkManager.callReachableWest()
}
}
The sub-suspend methods are calling a web service using retrofit. As it would return a boolean, I made it as an synchronous .execute() call.
fun callReachableEast(): Boolean {
return try {
val requestCall =
ApiService.create("eastApi").getReachabilityEast()
requestCall.execute().isSuccessful
} catch (exception: Exception) {
false
}
}
fun callReachableWest(): Boolean {
return try {
val requestCall =
ApiService.create("westApi").getReachabilityWest()
return requestCall.execute().isSuccessful
} catch (exception: Exception) {
false
}
}
I have gone through the below links
https://kotlinlang.org/docs/reference/coroutines/composing-suspending-functions.html
https://proandroiddev.com/async-operations-with-kotlin-coroutines-part-1-c51cc581ad33
and some more.
Repeating my question, How could I achieve without making the "isNetworkAvailable" as suspend?.
The syntax of a suspending function is similar to that of a regular function except for the addition of the suspend keyword. It can take a parameter and have a return type. However, suspending functions can only be invoked by another suspending function or within a coroutine.
If you notice the functions closely, they can be used to resume the coroutine with a return value or with an exception if an error had occurred while the function was suspended. This way, a function could be started, paused, and resume with the help of Continuation. We just have to use the suspend keyword.
BLOCKING: Function A has to be completed before Function B continues. The thread is locked for Function A to complete its execution. SUSPENDING: Function A, while has started, could be suspended, and let Function B execute, then only resume later. The thread is not locked by Function A.
To wait for a coroutine to finish, you can call Job. join . join is a suspending function, meaning that the coroutine calling it will be suspended until it is told to resume. At the point of suspension, the executing thread is released to any other available coroutines (that are sharing that thread or thread pool).
If you can't make isNetworkAvailable
a suspend
function, then it will be a blocking function. This means, any code calling isNetworkAvailable
will block as well, or you'd need to change this function's signature to have a callback instead.
First, let's look at the blocking version. There is a special coroutine-builder that is suited for bridging from the suspendable world into the regular/blocking world. It is called runBlocking
:
fun isNetworkAvailable(context: Context?): Boolean = runBlocking {
checkNetworkReachability(context)
}
...
val isAvailable = isNetworkAvailable(activity)
if (isAvailable) { ... }
...
If you'd like to change its signature and have a callback instead of a return-value:
fun CoroutineScope.isNetworkAvailable(context: Context?, callback: (Boolean) -> Unit) {
launch {
callback(checkNetworkReachability(context))
}
}
...
scope.isNetworkAvailable(activity) { isAvailable ->
if (isAvailable) { ... }
}
(code may have typos)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With