С помощью какого класса появляется трансформация suspend-функции

Ответ

Для трансформации suspend-функций в Java-совместимый код (например, для использования в RxJava или колбэках) используют класс Continuation. Kotlin компилятор автоматически преобразует suspend-функции в конечный автомат с Continuation, который управляет приостановкой и возобновлением корутин.

Пример с suspendCoroutine для ручного управления:

suspend fun fetchData(): String = suspendCoroutine { continuation ->
    someAsyncApi.call(object : Callback {
        override fun onSuccess(result: String) {
            continuation.resume(result)
        }
        override fun onError(error: Throwable) {
            continuation.resumeWithException(error)
        }
    })
}

Здесь continuation позволяет возобновить выполнение корутины после асинхронного вызова.

Ответ 18+ 🔞

Ёпта, ну слушай, тут такая тема интересная. Когда тебе надо из этих твоих приостановленных функций на Kotlin сделать что-то, что поймут в старом добром Java-мире — там, где правят бал RxJava или эти вездесущие колбэки — то тут на сцену выходит, блядь, класс Continuation.

Представляешь, компилятор Kotlin'а берёт твою suspend-функцию и делает с ней такую магию, что она превращается в этакий конечный автомат. А этот самый Continuation — он как дирижёр в этом оркестре, он управляет всей этой хуйней: где корутину приостановить, а где — ёпта — возобновить. Удивление пиздец, правда?

Ну а если ты хочешь сам всё пощупать и покрутить, то есть такой приём — suspendCoroutine. Это когда ты вручную, как заправский механик, управляешь этим процессом. Смотри, как это выглядит:

suspend fun fetchData(): String = suspendCoroutine { continuation ->
    someAsyncApi.call(object : Callback {
        override fun onSuccess(result: String) {
            continuation.resume(result) // Всё, приехали, возобновляемся с результатом
        }
        override fun onError(error: Throwable) {
            continuation.resumeWithException(error) // А тут, бля, с ошибкой
        }
    })
}

Вот видишь? Ты создаёшь этот самый continuation и держишь его, как козырь в рукаве. Пока твой какой-то левый асинхронный API там что-то делает, корутина висит, не дёргается. А как только приходит ответ — успешный или не очень — ты просто тычешь в континуэйшен: «На, братан, вот результат, давай дальше работай» или «Вот, слови исключение, разбирайся». И всё, машина снова запускается. Гениально и просто, как угол дома. Главное — не перепутать, где resume, а где resumeWithException, а то будет тебе хиросима, а не работающий код.