从背景线程中的房间查询中获取一个对象,并在视图中使用它。 android/kotlin/mvvm
在我当前的解决方案中,我使用coroutines,然后在viewmodel
中返回mutableLivedAta
。
DAO函数:
@Query(
"SELECT workout_name FROM workout_table " +
"WHERE id = :workoutId"
)
suspend fun getWorkoutName(workoutId: Long): String
存储库函数:
@WorkerThread
suspend fun getWorkoutName(workoutId: Long): String {
return database.workoutDao().getWorkoutName(workoutId)
}
ViewModel函数:
fun getWorkoutName(workoutId: Long): MutableLiveData<String> {
val workoutName = MutableLiveData<String>()
CoroutineScope(Dispatchers.IO).launch {
workoutName.postValue(repository.getWorkoutName(workoutId))
}
return workoutName
}
View .kt函数:
private fun setUpAppBar() {
binding?.apply {
viewModel.getWorkoutName(currentWorkoutId!!).observe(viewLifecycleOwner) {
editWorkoutTopAppbar.title = it
}
}
}
这有效,但我认为有更好的方法。我的主要问题是在viewModel
中,因为我正在制作mutableLivedAta
变量,将其返回视图并在准备就绪时给它一个值。
我看到的其他两种方法是从DAO和存储库函数中返回livedata
,并让视图观察它,但是这样,我认为数据库查询不是在背景线程中完成的。另一种方法是让View .KT文件启动Coroutine,但我相信该视图不应该启动Coroutines。
当存储库返回livedata时,使用coroutine的ViewModel
fun getWorkoutName(workoutId: Long): LiveData<String> {
CoroutineScope(Dispatchers.IO).launch {
return repository.getWorkoutName(workoutId)
}
}
会给我一个错误,因为我正在从Coroutine内部返回结果。
请让我知道解决方案,或者如果我以错误的方式解决此问题。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,最好使用
viewModelsCope
而不是创建新的Coroutines范围,因为ViewModelScope
如果Veiwmodel被销毁,则可以取消本身。其次,您需要将Livedata暴露于碎片或活动中,而不是untablelivedata,因为无法从外部操纵Livedata。因此,您的ViewModel应该看起来像这样:
First, it's better to use
viewModelScope
instead of creating new coroutines scope sinceviewModelScope
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: