Понимание идеи и вариантов использования suspendCoroutine

Я читаю «Глубокое погружение в Kotlin Coroutines» Марцина Москалы, и у меня проблема с пониманием функции suspendCoroutine.

AFAIK, suspendCoroutine — это низкоуровневый API, который помогает вам владеть объектом продолжения до приостановки работы сопрограммы и выполнять с ним какие-либо действия.

Как утверждает Марчин Москала,

он заканчивается лямбда-выражением ({ }). Функция передается как аргумент будет вызван перед приостановкой. Эта функция получает продолжение как аргумент. Функция suspendCoroutine позволяет использовать продолжение непосредственно перед приостановкой. После suspendCoroutine позвони, будет поздно.

Итак, что здесь на самом деле происходит? У меня есть следующие вопросы:

  1. Если мы поместим cont.resume(result), возобновится ли он еще до приостановки?
  2. Внутри лямбды есть синхронный код — какие-то тяжелые операции, например сетевой запрос. Так как же это приостановить? Он должен дождаться завершения операции и не приостанавливается внутри, поскольку все задачи синхронны. Даже API на основе обратного вызова должен выполняться синхронно. Я ошибаюсь?
  3. Тогда чем это отличается от прямого использования потоков, за исключением облегчения сопрограмм и т. д.?

Я знаю этот ответ, но до сих пор не понимаю

Я также знаю, что технически этот объект продолжения может быть сохранен, сопрограмма действительно приостанавливается, и позже мы можем вызвать .resume для сохраненного объекта в каком-то другом потоке управления, но этот сценарий, похоже, является неправильным использованием API сопрограмм из-за утечек памяти.

Это просто оболочка для обратных вызовов, чтобы избежать ада обратных вызовов?

Пожалуйста, разъясните идею использования suspendCoroutine.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

suspendCoroutine используется для соединения других асинхронных моделей, таких как обратные вызовы, фьючерсы и т. д., с сопрограммами. Он «преобразовывает» существующий асинхронный код в режим приостановки.

В целом схема использования такая:

  1. Приобретите продолжение и сохраните его где-нибудь.
  2. Вызовите асинхронную операцию (она выполняется в фоновом режиме).
  3. Возврат из лямбды, затем сопрограмма приостанавливается.
  4. В какой-то момент в будущем вызовите resume, чтобы возобновить работу сопрограммы. Как/где/когда мы вызываем resume во многом зависит от типа асинхронной операции и ее API.

Прямо отвечая на ваши вопросы:

Ад.1. Если мы поместим resume прямо в лямбду (что в некоторых случаях может иметь смысл), я подозреваю, что она даже не приостановится. Но он также может приостановить и немедленно возобновить работу. Я думаю, что эта функция не гарантирует ни одного из этих вариантов поведения.

Ад.2. Если мы поместим синхронный блокирующий код непосредственно в лямбду, это означает, что мы заблокировали сопрограмму аналогично тому, как если бы мы вообще не использовали suspendCoroutine. Это неправильный способ использования suspendCoroutine. Обычно ожидается, что лямбда, передаваемая suspendCoroutine, только планирует асинхронную операцию и завершается почти сразу.

Я также знаю, что технически этот объект продолжения может быть сохранен, сопрограмма действительно приостанавливается, и позже мы можем вызвать .resume для сохраненного объекта в каком-то другом потоке управления, но этот сценарий, похоже, является неправильным использованием API сопрограмм из-за утечек памяти.

Это просто оболочка для обратных вызовов, чтобы избежать ада обратных вызовов?

Это не неправильное использование API сопрограмм, это именно то, как мы должны использовать suspendCoroutine. Это не вызывает каких-либо утечек памяти, если предположить, что исходный код, основанный на обратных вызовах, не вызывал их.

Другие вопросы по теме

Похожие вопросы

Сериализатор для класса xxx не найден. Убедитесь, что класс помечен как «@Serializable» и что установлен плагин компилятора сериализации
Android: разрешения во время выполнения не работают — в настройках приложения не отображаются запрошенные разрешения, даже когда их запрашивают (WRITE_EXTERNAL_STORAGE)
Расшифровка зашифрованных данных Dart AES в Kotlin приводит к исключению BadPaddingException
Как получить доступ к частному свойству верхнего уровня Kotlin в безымянном (основном) файле?
Как читать и декодировать удаленные данные JSON в приложении Jetpack Compose?
Kotlin получает значение перечисления по его общему типу, если это перечисление
Десериализация JSON не работает в Jetpack Compose
Я не использовал «com.google.android.play:core:1.10.3» в проекте Gradle в студии Android
Я не использовал «com.google.android.play:core:1.10.3» в проекте Gradle в студии Android
Как я могу сделать коробку или карту похожей на мой дизайн?