简体   繁体   English

从使用 Kotlin 协程调用挂起函数的普通函数返回值

[英]Returning value from normal function which called suspend function using Kotlin Coroutine

Hi I am using Kotlin coroutine library in a project.嗨,我在一个项目中使用 Kotlin 协程库。

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.这里的 checkNetwork 是挂起函数。 Before executing it the return value is passed to the caller (View/Activity).在执行之前,返回值被传递给调用者(视图/活动)。 How could I achieve without making the "isNetworkAvailable" as suspend?.如果不将“isNetworkAvailable”设为挂起,我该如何实现?。

Inside the checkNetwork method, to check reach-ability calling network call as like below.在 checkNetwork 方法中,检查可达性调用网络调用,如下所示。

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.子挂起方法正在使用改造调用 Web 服务。 As it would return a boolean, I made it as an synchronous .execute() call.因为它会返回一个布尔值,所以我把它作为一个同步的 .execute() 调用。

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://kotlinlang.org/docs/reference/coroutines/composing-suspending-functions.html

https://proandroiddev.com/async-operations-with-kotlin-coroutines-part-1-c51cc581ad33 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?.重复我的问题,如何在不将“isNetworkAvailable”设为挂起的情况下实现?。

If you can't make isNetworkAvailable a suspend function, then it will be a blocking function.如果你不能让isNetworkAvailable成为一个suspend函数,那么它将是一个阻塞函数。 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.这意味着,任何调用isNetworkAvailable代码isNetworkAvailable将被阻塞,或者您需要更改此函数的签名以改为使用回调。

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 :它被称为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) (代码可能有错别字)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Kotlin 协程中挂起函数的问题 - Problem with suspend function in Kotlin coroutine 如果从协程调用非挂起函数会发生什么? - What happens if a non-suspend function is called from a coroutine? 从活动中调用协程 function 返回`应该只从协程或另一个挂起函数调用` - calling coroutine function from activity returns `should be called only from a coroutine or another suspend function` 挂起函数“callGetApi”只能从协程或另一个挂起函数中调用 - Suspend function 'callGetApi' should be called only from a coroutine or another suspend function 不适当的阻塞方法调用,但挂起函数“withContext”只能从协程或另一个挂起函数中调用 - Inappropriate blocking method call, but Suspend function 'withContext' should be called only from a coroutine or another suspend function 使用协程时出现挂起函数错误 - getting error of suspend function while using coroutine 在普通函数中调用 .enqueue 还是在 kotlin 挂起函数中调用 .execute 更好? - Is it better to call .enqueue in a normal function or .execute in a kotlin suspend function? 协程挂起函数和阻塞调用 - Coroutine suspend function and blocking calls 如果再次调用相同的函数,则取消 kotlin 中的挂起函数 - cancelling a suspend function in kotlin if the same function is called again 没有挂起函数的 Kotlin 协程 - Kotlin coroutine with no suspend functions
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM