Если вы видите определение launch :
fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job (source)
Это функция расширения CoroutineScope , поэтому ее необходимо вызывать в CoroutineScope .
Если вы используете runBlocking, он предоставит вам CoroutineScope как this
переменную в блоке, поэтому launch
неявно равно this.launch
.
Для запуска сопрограмма должна иметь жизненный цикл Job и CoroutineDispatcher , который содержится в CoroutineContext внутри CoroutineScope.
Итак, если вы хотите coroutine, есть две распространенные практики:
runBlocking (однопоточный запуск).
fun main() = runBlocking { // this: CoroutineScope
launch {} // implicit this.launch {}
}
фабричная функция coroutineScope (запускается с main поток, но при необходимости переключается на диспетчер по умолчанию).
suspend fun main() = coroutineScope { // this: CoroutineScope
launch {} // implicit this.launch {}
}