繁体   English   中英

从后台线程中的 Room 查询中获取单个 object 并在视图中使用它。 安卓/科特林/MVVM

[英]Get a single object from a Room query in a background thread and use it in the view. Android/Kotlin/MVVM

在我目前的解决方案中,我使用协程并在 view.kt class 观察到的ViewModel中返回一个MutableLiveData

道 function:

@Query(
    "SELECT workout_name FROM workout_table " +
        "WHERE id = :workoutId"
)
suspend fun getWorkoutName(workoutId: Long): String

存储库 function:

@WorkerThread
suspend fun getWorkoutName(workoutId: Long): String {
    return database.workoutDao().getWorkoutName(workoutId)
}

查看模型 function:

fun getWorkoutName(workoutId: Long): MutableLiveData<String> {
    val workoutName = MutableLiveData<String>()
    CoroutineScope(Dispatchers.IO).launch {
        workoutName.postValue(repository.getWorkoutName(workoutId))
    }
    return workoutName
}

查看.kt function:

private fun setUpAppBar() {
    binding?.apply {
        viewModel.getWorkoutName(currentWorkoutId!!).observe(viewLifecycleOwner) {
            editWorkoutTopAppbar.title = it
        }
    }
}

这行得通,但我认为有更好的方法可以做到这一点。 我的主要问题出在ViewModel中,因为我正在制作一个MutableLiveData变量,将其返回到视图并在准备就绪时为其赋值。

我见过的另外两种方法是从 DAO 和存储库函数返回LiveData并让视图观察它,但我认为这种方式不会在后台线程中完成数据库查询。 另一种方法是让 view.kt 文件启动协程,但我认为视图不应该启动协程。

存储库返回 LiveData 时使用协程的 ViewModel:

fun getWorkoutName(workoutId: Long): LiveData<String> {
    CoroutineScope(Dispatchers.IO).launch {
        return repository.getWorkoutName(workoutId)
    }
}

上面的代码给我一个错误,因为我从协程内部返回结果。

请让我知道一个解决方案,或者如果我以错误的方式解决这个问题。

首先,最好使用viewModelScope而不是创建新协程 scope,因为如果viewModelScope被销毁,viewModelScope 会自行取消。 其次,您需要将 LiveData 公开给片段或活动而不是 MutableLiveData,因为无法从外部操作 LiveData。

所以你的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM