Какова концепция CoroutineScope?

После прочтения введения и javadoc CoroutineScope я все еще немного запутался, что за идея CoroutineScope является.

Первое предложение документа "Определяет область для новых сопрограмм". мне не понятно: зачем моим сопрограммам нужна сфера?

Кроме того, почему автономные компиляторы не одобряются? Почему лучше сделать это:

fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
    for (x in 1..5) send(x * x)
}

вместо

fun produceSquares(): ReceiveChannel<Int> = produce { //no longer an extension function
    for (x in 1..5) send(x * x)
}

3 ответа

Вы все еще можете использовать глобальные "автономные" сопрограммы, порождая их в GlobalScope:

GlobalScope.launch {
    println("I'm running unstructured")
}

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

Используя структурированный параллелизм, то есть вложенные сопрограммы в свои области, вы в целом получите более удобную для сопровождения систему. Например, если вы создаете сопрограмму внутри другой, вы наследуете внешнюю область видимости. Это имеет несколько преимуществ. Если вы отменяете внешнюю сопрограмму, отмена будет делегирована ее внутренним сопрограммам. Кроме того, вы можете быть уверены, что внешняя сопрограмма не будет завершена, пока все ее дочерние сопрограммы не выполнят свою работу.

Там также очень хороший пример показан в документации для CoroutineScope,

CoroutineScope должен быть реализован на объектах с четко определенным жизненным циклом, которые отвечают за запуск дочерних сопрограмм. Примером такой сущности на Android является Activity.

Ведь первая твоя версия показана produceSquares методы лучше, так как это только исполняемый, если вызывается в CoroutineScope, Это означает, что вы можете запустить его внутри любой другой сопрограммы:

launch {
    produceSquares()
}

Сопрограмма, созданная внутри produceSquares наследует сферу launch, Вы можете быть уверены, что launch не завершается раньше produceSquares, Кроме того, если вы отменили launch, это также повлияет produceSquares,

Кроме того, вы все равно можете создать глобально запущенную сопрограмму, например:

GlobalScope.produceSquares()

Но, как уже упоминалось, это не лучший вариант в большинстве случаев.

Я также хотел бы рекламировать статью, которую я написал. Вот несколько примеров, демонстрирующих, что означают области: https://kotlinexpertise.com/kotlin-coroutines-concurrency/

Это связано с концепцией структурированного параллелизма, которая определяет структуру между сопрограммами.

На более философском уровне вы редко запускаете сопрограммы "глобально", как вы делаете с потоками. Сопрограммы всегда связаны с некоторой локальной областью в вашем приложении, которая представляет собой объект с ограниченным сроком службы, например элемент пользовательского интерфейса. Итак, при структурированном параллелизме мы теперь требуем, чтобы запуск вызывался в CoroutineScope, который является интерфейсом, реализованным вашими объектами с ограниченным сроком службы (такими как элементы пользовательского интерфейса или их соответствующие модели представлений).

Как очевидное следствие этой концепции: cancelв контексте scopeвсе его подкарутины тоже будут отменены.

Эта презентация kotlinconf представляет собой объяснение того, как coroutinesscope предоставляет полезную область отказов, а также соглашения о передовой практике для определения ваших собственных методов.

https://speakerdeck.com/elizarov/kotlin-coroutines-in-practice-at-kotlinconf-2018

https://www.youtube.com/watch?v=a3agLJQ6vt8

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