Как вернуть один объект (не LiveData) из комнаты с помощью сопрограмм - PullRequest
0 голосов
/ 04 апреля 2020

Room выполняет запросы, которые автоматически возвращают LiveData в фоновом потоке. Но я хочу вернуть одно значение, которое не обернуто в LiveData (потому что я не хочу живых обновлений). Как мне реализовать это с помощью сопрограмм?

Как вернуть объект Task из этой функции?

fun getTask(id: Int): Task {
    viewModelScope.launch {
        repository.getTask(id)
    }
}

Эта функция находится внутри ViewModel. Он перенаправляет вызов в DAO:

@Query("SELECT * FROM task_table WHERE id = :id")
fun getTask(id: Int): Task

Ответы [ 2 ]

0 голосов
/ 07 апреля 2020

Одним из обходных путей может быть немедленный возврат отложенного объекта, а затем вызов .await() для отложенного возврата

fun getTaskAsync(id: Int): Deferred<Task> = viewModelScope.async {
        repository.getTask(id)
    }

//call-site
getTaskAsync(id).await() // <- this is suspension point
0 голосов
/ 06 апреля 2020

Если вы не вернете LiveData из комнаты, вы не будете получать обновления из БД. Однако вы можете вернуть LiveData из вашего viewModel.

val data = liveData {
    emit(repository.getTask(id))
}

Функция расширения liveData запускается в сопрограмме, а затем вы можете использовать приостановленную версию DAO для правильной обработки фона.

@Query("SELECT * FROM task_table WHERE id = :id")
suspend fun getTask(id: Int): Task?

Главное, что вам нужно сделать, это убедиться, что оно имеет значение null, если вы не используете агрегатную функцию в своем запросе.

Если вы действительно хотите вызвать метод в вашем viewModel для возврата задание, которое вы должны запустить из своей деятельности / фрагмента (не рекомендуется)

ViewModel
suspend fun getTask(id: Int): Task {
    repository.getTask(id)
}

Activity/Fragment
lifecycleScope.launch {
    val task = viewModel.getTask(id)
    // Do What you want with the task
}
...