[英]Get a single object from a Room query in a background thread and use it in the view. Android/Kotlin/MVVM
In my current solution to this I use coroutines and return a MutableLiveData
in the ViewModel
that the view.kt class observes.在我目前的解决方案中,我使用协程并在 view.kt class 观察到的
ViewModel
中返回一个MutableLiveData
。
DAO function:道 function:
@Query(
"SELECT workout_name FROM workout_table " +
"WHERE id = :workoutId"
)
suspend fun getWorkoutName(workoutId: Long): String
Repository function:存储库 function:
@WorkerThread
suspend fun getWorkoutName(workoutId: Long): String {
return database.workoutDao().getWorkoutName(workoutId)
}
ViewModel function:查看模型 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:查看.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.我的主要问题出在
ViewModel
中,因为我正在制作一个MutableLiveData
变量,将其返回到视图并在准备就绪时为其赋值。
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.我见过的另外两种方法是从 DAO 和存储库函数返回
LiveData
并让视图观察它,但我认为这种方式不会在后台线程中完成数据库查询。 Another way is having the view.kt file launch the coroutine but I believe the view is not supposed to launch coroutines.另一种方法是让 view.kt 文件启动协程,但我认为视图不应该启动协程。
The ViewModel using a coroutine when repository returns LiveData:存储库返回 LiveData 时使用协程的 ViewModel:
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.首先,最好使用
viewModelScope
而不是创建新协程 scope,因为如果viewModelScope
被销毁,viewModelScope 会自行取消。 secondly, you need to expose a LiveData to fragment or activity instead of MutableLiveData because LiveData can not be manipulated from outside.其次,您需要将 LiveData 公开给片段或活动而不是 MutableLiveData,因为无法从外部操作 LiveData。
so your viewModel should look something like this:所以你的 viewModel 应该看起来像这样:
private val _workoutName = MutableLiveData<String>()
val workoutName : LiveData<String>() get() = _workoutName
fun getWorkoutName(workoutId: Long) {
viewModelScope.launch {
_workoutName.postValue(repository.getWorkoutName(workoutId))
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.