如何将 viewModelScope.launch{} 的结果作为函数的 return 值发送?

How to send the result of viewModelScope.launch{} as the return value of a function?

在下面的代码片段中,如何在 viewModelScope.launch完成后获取isValid 的值。

viewModelScope.launch 最后运行,在 fun checkCode() 里面。所以 fun checkCode() 总是 return false。

fun someListener() {
    if (checkCode() == true) {
        //do something
    }
}

fun checkCode(): Boolean {
    var isValid = false

    viewModelScope.launch(Dispatchers.Main) {
        val response = withContext(Dispatchers.IO) {
            // something do in background
        }
        
        if (response == "someString") {
            isValid = true
            // tried to type "return isValid" but syntax error
        }
    }
    
    // the problem is below statements run before viewModelScope.launch
    if (isValid) return true
    else return false
}

viewModelScope.launch 将始终 return 一个 Job。所以你不能真正 return 从中得到一个值。为了获得你想要的,你可以像下面这样改变你的代码风格:

fun someListener() {
    viewModelScope.launch {
        if (checkCode() == true) {
            //do something
        }
    }
}

suspend fun checkCode(): Boolean {
    var isValid = false

    val response = withContext(Dispatchers.IO) {
            // something do in background
    }
        
    if (response == "someString") {
        isValid = true
    }
    
    return isValid
}

使该函数成为挂起函数,运行 协程中的所有内容,包括该函数及其 return。由于在等待协程完成时无法阻塞主线程,因此需要将其设置为挂起函数,以便它可以挂起而不阻塞。

您的最终结果将如下所示:

fun someListener() {
    viewModelScope.launch(Dispatchers.Main) {
        if (checkCode() == true) {
            //do something
        }
    }
}

suspend fun checkCode(): Boolean {
    val response = withContext(Dispatchers.IO) {
        // something in background
    }
        
    if (response == "someString") {
        return true
    }
    
    return false
}

suspend 函数在后台线程上运行。要从该函数而不是使用 return 获取结果,请使用 LiveData.

private val _isValid = MutableLiveData<Boolean>()
val isValid: LiveData<Boolean> // To observe the value outside the ViewModel class.
get() = _isValid

...
suspend fun doBackgroundWork() {
   ...
   _isValid.postValue(true)
   ...
}

现在您可以在后台线程中更新私有值,并在视图控制器中观察这一点(Fragment/Activity),当您获得更新值时进行适当的操作。

使用来自 Documentation

的 liveData 的几种不同方式