Функция расширения CoroutineScope в другом классе - PullRequest
0 голосов
/ 14 марта 2019

Я пытаюсь использовать забавное расширение для CoroutineScope.(), чтобы запустить некоторую асинхронную работу.Я не уверен, как вызвать этот метод из моего основного класса, см. Ниже:

class MyService {
   fun CoroutineScope.getFoo() = async(IO/Single/Default) { //work }
}

class MyProgram(val service : MyService) : CoroutineScope {

   fun main() {
      launch {
         val deferred = service.getFoo() // doens't work, can't find getFoo

         // works, but looks a bit odd IMO, is there a better way?
         val deferred = with(service) { getFoo() }

         //some work

         deferred.await()
      }

   }

}

Я знаю, что мог бы просто переместить ключевое слово async {} в мой основной метод, но в этом случае вызывающая сторонадолжен был бы решить планировщик, я не думаю, что это путь.

Служба знает природу своей работы (однопотоковое ограничение ввода-вывода / вычислений? И т. Д.), И я думаю, что именно он решает планировщик.

Ответы [ 2 ]

1 голос
/ 14 марта 2019

Насколько я понимаю, вы хотите, чтобы служба указала планировщик. Почему бы не разделить спецификацию планировщика и решение работать асинхронно?

Позвольте сервисной функции быть приостановленной и используйте withContext для указания планировщика. И пусть вызывающая сторона решит, должна ли функция выполняться асинхронно.

class MyService {
    suspend fun getFoo() = withContext(Dispatchers.IO) {
        //work 
    }
}

abstract class MyProgram(val service: MyService) : CoroutineScope {

    fun main() {
        launch {
            val deferred = async { service.getFoo() }

            //some work

            deferred.await()
        }
    }
}
1 голос
/ 14 марта 2019

Почему бы не сделать getFoo нормальной функцией и передать ее в область действия:

fun getFoo(scope: CoroutineScope) = scope.async {
    //work }
}

launch {
    service.getFoo(this)
}
...