从背景线程中的房间查询中获取一个对象,并在视图中使用它。 android/kotlin/mvvm

发布于 2025-01-31 11:38:24 字数 1560 浏览 2 评论 0原文

在我当前的解决方案中,我使用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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

衣神在巴黎 2025-02-07 11:38:24

首先,最好使用viewModelsCope而不是创建新的Coroutines范围,因为ViewModelScope如果Veiwmodel被销毁,则可以取消本身。其次,您需要将Livedata暴露于碎片或活动中,而不是untablelivedata,因为无法从外部操纵Livedata。

因此,您的ViewModel应该看起来像这样:


private val _workoutName = MutableLiveData<String>()
val workoutName : LiveData<String>() get() = _workoutName


fun getWorkoutName(workoutId: Long) {
    viewModelScope.launch {
        _workoutName.postValue(repository.getWorkoutName(workoutId))
    }
}

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))
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文