Обработка последовательностей в сопрограммах

Я пытаюсь использовать последовательность (например, FileTreeWalk, возвращенный из File.walk) внутри сопрограммы, но моя реализация продолжает блокировать поток пользовательского интерфейса.

Есть ли хороший способ обрабатывать последовательности и отображать элементы в сопрограммах?

Вот фрагмент моего кода:

override fun onResume() {
  super.onResume()
  launch {
    apkFiles = searchMyFiles(rootDir).await()
    showMyFiles()
  }
}

private fun searchMyFiles(dir: File): Deferred<MutableList<MyFile>> {
  return async {
    dir.walk().filter { !it.isDirectory }
      .filter { it.extension.equals(MY_EXTENSION, true) }
      .map { MyFile(it, context) }.filter { it.valid 
    }.sorted().toMutableList()
  }
}

person G00fY    schedule 28.10.2018    source источник


Ответы (1)


Хотя в вашем коде нет свидетельств, я предполагаю, что вашим диспетчером по умолчанию, установленным в CoroutineScope, который вы неявно используете, является Dispatchers.Main (поток пользовательского интерфейса). Вы продолжаете использовать тот же диспетчер для фоновой работы вместо Dispatchers.IO.

Во-вторых, вы используете async-await без цели, вместо этого вы должны использовать withContext и объявить свою функцию как suspend fun.

Учитывая вышеизложенное, ваш код должен быть

override fun onResume() {
    super.onResume()
    launch {
        apkFiles = searchMyFiles(rootDir)
        showMyFiles()
    }
}

private suspend fun searchMyFiles(dir: File) : MutableList<MyFile> = 
    withContext(Dispatchers.IO) {
        dir.walk()
           .filter { !it.isDirectory }
           .filter { it.extension.equals(MY_EXTENSION, true) }
           .map { MyFile(it, context) }
           .filter { it.valid }
           .sorted()
           .toMutableList()
    }
}
person Marko Topolnik    schedule 29.10.2018
comment
Большое спасибо! Похоже, я неправильно использовал прицел. Моя первоначальная мысль заключалась в том, что действие внутри оператора карты должно выполняться в отдельной сопрограмме. - person G00fY; 29.10.2018
comment
Ленивая обработка последовательности на самом деле не имеет значения, потому что toMutableList - это терминальная операция, и она с нетерпением собирает все в список. - person Marko Topolnik; 29.10.2018