簡體   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