Давайте поговорим об одном из компонентов составляющих понятия Корутины Suspend-функции. Помните мы говорили о том что Корутины не блокируют поток, а приостанавливают работу кода. Ну так вот, такое свойство обеспечивает Suspend-функция. То есть, код который вписан в тело Suspend-функции при запуске не заблокирует поток, но этот код приостановит свою работу. Это означает что мы можем даже запустить Корутину в Main-потоке. Давайте приведем пример:

val url = "http://myurl.com/file.pdf"

// long synchronous function

getFile(url)

println("File is downloaded")

Простой пример, в котором пытаемся загрузить файл по определенному URL. Здесь функция getFile() синхронная, то есть блокирует поток. Но чтобы запускать функцию из основного потока нам нужно будет сделать ее асинхронной и прокинуть в нее лямбду-коллбек с функцией println(), который будет выполнен после загрузки файла:

getFile(url) { println("File is downloaded") }

Из выше сказанного следует что, при запуске массивного кода(с тяжелыми вычислениями) в основном потоке нам придется либо блокировать основной поток либо писать колбэк(и плодить колбэкхэлл)

Но благодаря Корутинам и саспенд-функции у нас возможность написать код в которой тяжелая функция не блокирует поток но и код который стоит после этой функции выполнялся после завершения тяжелой функции без коллбэков. Давайте посмотрим как это сделать в переписанном примере:

CoroutineScope(Job()).launch {
	val url = "http://myurl.com/file.pdf"

	// long synchronous function
	suspendedGetFile(url)

	println("File is downloaded")
}

Тут launch — это Builders, который создает Корутину. В ее теле появилась Suspend-функция suspendedGetFile(url). Помните? Builder, Suspend-функция все это части Корутины. Эту конструкцию мы можем назвать Корутиной. Ну так вот, эта Корутина не блокирует поток и ее можно запустить в основном потоке. Suspend-функция suspendedGetFile() запустит загрузку файла в рабочем потоке, а функция println() отработает после завершения функции suspendedGetFile().

+ Suspend-функция возвращает свой ответ асинхронно поэтому ее нельзя вызвать из обычной функции
+ Suspend-функция может выполнять код в разных потоках. Нужно помнить про возможный рассинхрон, так как нет гарантии что исполнение и возврат ответа будет на одном потоке

Пусть это и выглядит как фантастика, но помните что Котлин-код далее будет трансформирован в Java-классы. И в процессе этих преобразований наша Корутина будет трансформирована и будет использован механизм Continuation. Все наши компоненты Корутины «под капотом» реализуют колбэк, который выполнит println() после загрузки suspendedGetFile().