Базовый сетевой вызов сопрограммы в библиотеке

Я просто читаю и изучаю сопрограммы в Котлине, чтобы использовать их в небольшой библиотеке для развлечения/обучения. В документации вы можете сделать что-то вроде

GlobalScope.launch {

}

Итак, в моем методе

fun myMethod() {
    GlobalScope.launch {
        // do some networking code
    }   
}

Лучше всего использовать GlobalScope для запуска сопрограммы для библиотеки? В документах написано

Application code usually should use application-defined CoroutineScope, using async or launch on the instance of GlobalScope is highly discouraged.

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

я тоже пробовал

runBlocking {
    async {
        // do some networking code
    }
}

Думая, что runBlocking вводит новую область сопрограммы, но я думаю, что в этом случае она наследует область от своих родителей, которая является основным потоком, поэтому я получаю исключение об отсутствии сети в основном потоке пользовательского интерфейса.

Я бы подумал, что библиотека должна предоставлять функции приостановки и позволять пользователю обрабатывать контекст выполнения потоков, но кто знает наверняка.

EpicPandaForce 26.02.2019 21:12

@EpicPandaForce. Спасибо. Мне было интересно, было ли это также «лучшей практикой», когда функции приостанавливали функции для клиента, чтобы использовать их по мере необходимости.

Crystal 26.02.2019 21:20
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
2
288
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Вы можете создать функцию приостановки, и это обеспечит, чтобы пользователь сам вызывал ее из сопрограммы. Если ваш метод использует withContext, вам не нужно беспокоиться о GlobalScope или настройке области действия. withContext просто сообщает сопрограмме, какой контекст использовать (для работы в сети вам понадобится IO. И область теперь определяется тем, как пользователь запускает ее.

Я бы построил ваш метод следующим образом:

suspend fun myMethod() = withContext(Dispatchers.IO) {
    // do some networking code
}

В зависимости от того, чего вы пытаетесь достичь, вы можете использовать разные шаблоны даже внутри библиотеки.

Если ваша функция должна быть немедленно вернуться после запуска некоторых сопрограмм, «лучшей практикой» будет объявить вашу функцию как расширение CoroutineScope, чтобы вам не нужно было использовать глобальную область видимости:

fun CoroutineScope.launchesAndReturnsImmediately() {
    // launch can be called because we are extending CoroutineScope
    launch {
        // some work
    }
}

При этом вы часто не нужно возвращаться немедленно в библиотеке, поэтому вместо этого вы можете объявить свои функции suspend, что легче понять на стороне потребителя. Там несколько вариантов:

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

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