Home > Back-end >  How to write a coroutine function in BaseViewModel that can be used in child ViewModel
How to write a coroutine function in BaseViewModel that can be used in child ViewModel

Time:11-22

I write a BaseViewModel below

open class BaseViewModel : ViewModel() {

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

use child viewModel extend it and it works.

(getUserProfile() is a suspend function)

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)
            }
        }
    }
}

and i want to move coroutinesScope.launch into BaseViewModel so i write the launch function

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)
            }
        }
    }
}

Getting 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) {

                }
            }
        }
    }
}

how to solve it, thanks.

CodePudding user response:

You need to mark the lambda in launch with suspend modifier as

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

Also there is no need to define your own coroutine scope in ViewModel, you can simply use the ViewModelScope

  • Related