In my current solution to this I use coroutines and return a MutableLiveData
in the ViewModel
that the view.kt class observes.
DAO function:
@Query(
"SELECT workout_name FROM workout_table " +
"WHERE id = :workoutId"
)
suspend fun getWorkoutName(workoutId: Long): String
Repository function:
@WorkerThread
suspend fun getWorkoutName(workoutId: Long): String {
return database.workoutDao().getWorkoutName(workoutId)
}
ViewModel function:
fun getWorkoutName(workoutId: Long): MutableLiveData<String> {
val workoutName = MutableLiveData<String>()
CoroutineScope(Dispatchers.IO).launch {
workoutName.postValue(repository.getWorkoutName(workoutId))
}
return workoutName
}
View.kt function:
private fun setUpAppBar() {
binding?.apply {
viewModel.getWorkoutName(currentWorkoutId!!).observe(viewLifecycleOwner) {
editWorkoutTopAppbar.title = it
}
}
}
This works but I think there's a better way of doing this. My main problem is in the ViewModel
because I'm making a MutableLiveData
variable, returning it to the view and giving it a value when ready.
Two other ways I've seen is returning LiveData
from the DAO and repository functions and having the view observe it, but this way I think the database query is not done in a background thread. Another way is having the view.kt file launch the coroutine but I believe the view is not supposed to launch coroutines.
The ViewModel using a coroutine when repository returns LiveData:
fun getWorkoutName(workoutId: Long): LiveData<String> {
CoroutineScope(Dispatchers.IO).launch {
return repository.getWorkoutName(workoutId)
}
}
The above code gives me an error because I'm returning the result from inside a coroutine.
Please let me know a solution, or maybe if I'm approaching this problem the wrong way.
First, it's better to use viewModelScope
instead of creating new coroutines scope since viewModelScope
cancels itself if the veiwModel gets destroyed. secondly, you need to expose a LiveData to fragment or activity instead of MutableLiveData because LiveData can not be manipulated from outside.
so your viewModel should look something like this:
private val _workoutName = MutableLiveData<String>()
val workoutName : LiveData<String>() get() = _workoutName
fun getWorkoutName(workoutId: Long) {
viewModelScope.launch {
_workoutName.postValue(repository.getWorkoutName(workoutId))
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.