С новой стабильной версией сопрограмм kotlin я пытался реализовать одну из функциональных возможностей моего приложения, используя ее. Но я немного запутался.
По сути, у меня есть функция, которая выполняет некоторую работу со списком элементов. Это занимает около 700-1000 мс.
fun processList(list : ArrayList<String>) : ArrayList<Info> {
val result = mutableListOf<Info>()
for (item in list) {
// Process list item
// Each list item takes about ~ 15-20ms
result.add(info) // add processed info to result
}
return result // return result
}
Теперь я хотел, чтобы это не блокировало основной поток. Поэтому я запускаю эту функцию внутри блока запуска, чтобы она не блокировала основной поток.
coroutineScope.launch(Dispatchers.Main) {
val result = processList(list)
}
Это просто отлично работает.
Но я попытался сделать функцию приостановленной, чтобы убедиться, что она никогда не блокирует основной поток. На самом деле, внутри функции нет никаких других сопрограмм. Также попытался обработать каждый элемент списка в отдельной сопрограмме, а затем объединить их все, чтобы он фактически использовал дочернюю сопрограмму. Но этот блок внутри цикла использует синхронизированный вызов метода. Так что нет смысла делать его асинхронным - параллельным. Таким образом, я получаю функцию приостановки, как это:
suspend fun processList(list : ArrayList<String>) : ArrayList<Info> = coroutineScope {
val result = mutableListOf<Info>()
for (item in list) {
// Process list item
// Each list item takes about ~ 15-20ms
result.add(info) // add processed info to result
}
return result // return result
}
В начале есть только модификатор suspend, а блок метода заключен в coroutineScope { }
.
Это все еще имеет значение? Какой из них лучше? Должен ли я сделать функцию приостановки функции, только если она использует сопрограмму, ИЛИ долго выполняющиеся функции также должны быть помечены как функция приостановки?
Я в замешательстве. Я смотрел все недавние разговоры о сопрограммах, но не смог прояснить этот момент.
Может кто-нибудь помочь мне понять это?
UPDATE:
Так что в итоге у меня появилась такая функция. Просто чтобы убедиться, что функция никогда не вызывается в основном потоке. И вызывающая функция не должна везде помнить, что это нужно вызывать в фоновом потоке. Таким образом, я могу сделать вещи абстрактными для вызывающей функции: Просто делайте все, что вам говорят, мне все равно, где вы хотите обрабатывать вещи. Просто обработайте и дайте мне результаты. Так что функция сама заботится о том, где она должна выполняться, а не о вызывающей функции.
suspend fun processList(list : ArrayList<String>) : ArrayList<Info> = coroutineScope {
val result = mutableListOf<Info>()
launch(Dispatchers.Default) {
for (item in list) {
// Process list item
// Each list item takes about ~ 15-20ms
result.add(info) // add processed info to result
}
}.join() // wait for the task to complete on the background thread
return result // return result
}
Это правильный путь?