Котлин: структура для последовательных сопрограмм - PullRequest
0 голосов
/ 19 февраля 2019

Я создаю приложение диспетчера библиотек для Android и пытаюсь создать представление для отображения иерархии «коллекций» (т. Е. Папок) от текущей коллекции до корневой.

База данных реализована с помощьюКомната (доступ косвенно через collectionRepo).Каждый объект Collection имеет уникальный ключ и знает ключ своего родителя.

Что я пытаюсь сделать:

  1. Учитывая ключ текущей коллекции, создайте иерархию Collection до root.
  2. После того, как это будет завершено, создайте визуализацию пользовательского интерфейса иерархии.

Кажется, что это должно быть довольно просто с сопрограммами Котлина, но я не смог получитьсопрограммы структурированы правильно.

Поскольку каждый вызов collectionRepo.getCollection(curKey) в конечном счете выполняет запрос Room db, он должен быть вне основного потока.Но мне нужно дождаться возврата запроса, чтобы узнать, какой родительский ключ необходим для последующего запроса.

private suspend fun buildBackstackView() {

    var curKey = collectionViewModel.getCurrentCollectionKey()

    coroutineScope {
        launch {
            do {
                val curCollection = when (curKey) {
                    "" -> {
                        Collection("", 0, "TOP", "") // collection's parent is root - create a fake root Collection to push to the stack
                    }
                    else -> {
                        collectionRepo.getCollection(curKey) // ultimately a Room database query
                    }
                }

                collectionStack.add(curCollection)
                curKey = curCollection.key

            } while (curKey != "")
        }
    }

    withContext(Dispatchers.Main) {

        ...build UI view using collectionStack...

    }
}

В ответ на запрос Сергея collectionRepo.getCollection () просто передает запрос в DAOметод, который определяет запрос Room.

@Query("SELECT * FROM collections WHERE `key` = :colKey LIMIT 1")
fun getCollection(colKey: String): Collection

1 Ответ

0 голосов
/ 19 февраля 2019

Пожалуйста, проверьте следующий код, он должен помочь вам:

    // creating local scope for coroutines
    private var job: Job = Job()
    private val scope = CoroutineScope(Dispatchers.Main + job)     

    // call this to cancel job when you don't need it anymore, for example in Activity.onDestroy() method
    fun cancelJob() {
        job.cancel()
    }

    private fun buildBackstackView() {
        var curKey = collectionViewModel.getCurrentCollectionKey()

        scope.launch {
            do {
                val curCollection = when (curKey) {
                    "" -> {
                        Collection("", 0, "TOP", "")
                    }
                    else -> withContext(Dispatchers.IO) { // runs in background thread suspending the coroutine
                        collectionRepo.getCollection(curKey)
                    }

                }

                collectionStack.add(curCollection)
                curKey = curCollection.key

            } while (curKey != "")

            // ...build UI view using collectionStack...
        }
    }

Для использования Dispatchers.Main импорт:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1'
...