android - 使用 Kotlin Coroutine 从调用挂起函数的普通函数返回值

标签 android kotlin async-await kotlin-coroutines coroutinescope

您好,我正在项目中使用 Kotlin 协程库。

下面的方法调用一个返回 bool 值的挂起函数。

fun isNetworkAvailable(context: Context?): Boolean {
            //return checkNetworkReachability(context)
            var isNetworkAvailable = false
            GlobalScope.launch(Dispatchers.Default) {
                isNetworkAvailable = GlobalScope.async<Boolean> {
                    checkNetwork()

                }.await()
            }
            return isNetworkAvailable

        }

这里的 checkNetwork 是挂起函数。在执行它之前,返回值被传递给调用者( View /Activity )。 如果不将“isNetworkAvailable”设为暂停,我如何实现?

在 checkNetwork 方法中,检查可达性调用网络调用,如下所示。

private suspend fun checkNetwork() : Boolean {
            val value = GlobalScope.async<Boolean> {
                val isEastReachable = async { checkEastReachable() }
                if (!isEastReachable.await()) {
                    checkWestReachable()
                } else {
                    true
                }
            }

            return value.await()
        }

子方法是

private suspend fun checkEastReachable(): Boolean = coroutineScope {

                withContext(Dispatchers.Default) {
                    repository.networkManager.callReachableEast()
                }
            }



private suspend fun checkWestReachable(): Boolean = coroutineScope {

                withContext(Dispatchers.Default) {
                    repository.networkManager.callReachableWest()
                }
            }

sub-suspend 方法正在使用改造调用 Web 服务。因为它会返回一个 bool 值,所以我将其作为同步 .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
        }
    }

我已经浏览了以下链接

https://kotlinlang.org/docs/reference/coroutines/composing-suspending-functions.html

https://proandroiddev.com/async-operations-with-kotlin-coroutines-part-1-c51cc581ad33

还有一些。

重复我的问题,如果不将“isNetworkAvailable”设为挂起,我如何实现?

最佳答案

如果您不能使isNetworkAvailable 成为suspend 函数,那么它将是一个阻塞函数。这意味着,任何调用 isNetworkAvailable 的代码也会被阻止,或者您需要更改此函数的签名以改为使用回调。

首先,让我们看一下阻塞版本。有一个特殊的协程构建器,适用于从可暂停世界桥接到常规/阻塞世界。它被称为 runBlocking:

fun isNetworkAvailable(context: Context?): Boolean = runBlocking {
    checkNetworkReachability(context)
}

...

val isAvailable = isNetworkAvailable(activity)
if (isAvailable) { ... }
...

如果您想更改其签名并使用回调而不是返回值:

fun CoroutineScope.isNetworkAvailable(context: Context?, callback: (Boolean) -> Unit) { 
    launch {
        callback(checkNetworkReachability(context))
    }
}

...
scope.isNetworkAvailable(activity) { isAvailable ->
    if (isAvailable) { ... }
}

(代码可能有错别字)

关于android - 使用 Kotlin Coroutine 从调用挂起函数的普通函数返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56276046/

相关文章:

android - 未知数据绑定(bind)属性 : onLongClick - Attribute exists and works

android - AsyncTask 中的上下文

android - Android gradle问题(当前2.4必需2.8)Android Studio

android - Kotlin 中的 Intent

java - 在 '@'之前屏蔽电子邮件中的中间字符

java - Android - 如何持续监听 Fragment 类的静态变量变化?

intellij-idea - TornadoFX Unresolved JavaFx

javascript - python 与 JavaScript 中的异步等待之间的区别

c# - 在ShowDialog之后立即从ViewModel执行操作

typescript - 在 Typescript 中使用数组迭代简化异步等待