如何在 BaseViewModel 中编写可在子 ViewModel 中使用的协程函数

How to write a coroutine function in BaseViewModel that can be used in child ViewModel

下面写一个BaseViewModel

open class BaseViewModel : ViewModel() {

    private val coroutinesScope = CoroutineScope(Dispatchers.Default + Job())
    val errorMessage: MutableLiveData<String> = MutableLiveData()
}

使用子 viewModel 扩展它并且它有效。

getUserProfile()是一个挂起函数)

class AAA : BaseViewModel() {

    fun getUserProfile() {

        coroutinesScope.launch {
            try {
                ApiService.Account.getUserProfile().let { profile ->// works
                    if (profile.success) {

                    }
                }
            } catch (e: Exception) {
                errorMessage.postValue(Constant.System_error)
            }
        }
    }
}

我想将 coroutinesScope.launch 移动到 BaseViewModel 所以我写了 launch 函数

open class BaseViewModel : ViewModel() {

    val coroutinesScope = CoroutineScope(Dispatchers.Default + Job())
    val errorMessage: MutableLiveData<String> = MutableLiveData()

    fun launch(function: () -> Unit) {
        coroutinesScope.launch {
            try {
                function.invoke()
            } catch (e: Exception) {
                errorMessage.postValue(Constant.System_error)
            }
        }
    }
}

获取错误suspend function can only be called within coroutine body

class AAA : BaseViewModel() {

    fun getUserProfile() {

        launch {

            ApiService.Account.getUserProfile().let { profile ->// getting compile error
                if (profile.success) {

                }
            }
        }
    }
}

如何解决,谢谢

您需要将 launch 中的 lambda 标记为 suspend 修饰符

fun launch(function: suspend () -> Unit) {
    coroutinesScope.launch {
        try {
            function.invoke()
        } catch (e: Exception) {
           errorMessage.postValue(Constant.System_error)
        }
     }
}

也不需要在ViewModel中定义你自己的协程范围,你可以简单地使用ViewModelScope