Сопрограммы Kotlin: почему это не вызывает исключение NetworkOnMainThreadException? - PullRequest
0 голосов
/ 18 марта 2019

client использует адаптер сопрограммы Retrofit.

Я не понимаю, почему я не получаю NetworkOnMainThreadException ??Разве это не вызывается в главном потоке ??

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val deferred = client.getStuffDeferred(file)
    CoroutineScope(Dispatchers.Main).launch {
        val response = deferred.await()
    }
}

Ответы [ 2 ]

0 голосов
/ 18 марта 2019

если вы вызываете launch на Dispatchers.Main, он запускается в основном потоке, но приостанавливает выполнение, чтобы не блокировать поток.

Так, чтобы это поведение не блокировало и не генерировало исключение NetworkOnMainThreadException, посколькуне приостанавливать методы или методы runBlocking в вашем CoroutineScope

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

withContext(Dispatchers.IO){// your suspended calls}

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

Ознакомьтесь с этой статьей для Solution3, котораяиспользуйте сопрограмму

0 голосов
/ 18 марта 2019

Если вы передадите Coroutine Context своему компилятору сопрограмм, то такая сопрограмма будет использовать этот поток для выполнения.

т.е.

  1. Dispatchers.Default - используется всеми стандартными сборщиками, если в их контексте не указан ни диспетчер, ни какой-либо другой ContinuationInterceptor. Он использует общий пул общих фоновых потоков. Это подходящий выбор для сопрограмм с интенсивными вычислениями, которые потребляют ресурсы ЦП.
  2. Dispatchers.IO - использует общий пул потоков, созданных по требованию, и предназначен для разгрузки операций блокирования с интенсивным вводом-выводом (таких как файловый ввод-вывод и блокирующий ввод-вывод сокетов).
  3. Dispatchers.Unconfined - запускает выполнение сопрограммы в текущем кадре вызова до первого приостановления. При первом приостановлении возвращается функция компоновщика сопрограмм. Сопрограмма возобновляется в любом потоке, который используется соответствующей функцией приостановки, не ограничивая его каким-либо конкретным потоком или пулом. Неограниченный диспетчер не должен обычно использоваться в коде.
  4. Частные пулы потоков могут быть созданы с newSingleThreadContext и newFixedThreadPoolContext.
  5. Произвольный Executor может быть преобразован в диспетчер с функцией расширения asCoroutineDispatcher.

Итак, используйте как:

CoroutineScope(Dispatchers.IO).launch { // we should use IO thread here !

}
...