нас есть вызов саспенд фукции на 10-ой строке и есть несколько вопросов
1) Тк метод саспенд, то он требует, чтобы и вызывающая функция тоже была саспенд либо вызывался из корутины. Это просто прихоть разработчиков? Это ведь не андроид, где нужно делать ИО в отдельном потоке
2) Второй вопрос скорее уточнение и мое непонимание. На той же 10ой строке указывается, что метод саспенд, и я все время думал, этот метод и останавливает выполнение кода, отдавая возможность другим корутинам сработать в это время? Или оно саспендится когда угодно?
3) Не смотря на вызов саспенд метода, 2-йка печатается только после ответа с сервера, то есть запрос не пропускается и останавливается весь блок кода? (если, конечно, внутри не вызывается корутина, но тогда были бы вопросы к логике)
1) suspend - это точка остановки, это не прихоть разработчиков, это маркер. 2) suspend останавливает выполнение корутины до конца выполнения функции 3) ответ во втором
1) я в том плане, зачем было обозначать метод саспенд, если его можно вызывать только из корутины, а обычную функцию когда угодно. Но ладно, это мелочь, спасибо 2) то есть если у меня есть условный метод foo() где внутри 3 саспенд функции, то функция foo "засаспендится" 3 раза на методах bar(), а простой код будет выполнять без установки? (код упрощен) fun foo() { var a = 42 bar1() a++ bar2() a++ bar3() a++ }
1) может потому-что он саспендит поток? А так будет только корутину? 2) нет, всё будет выполнятся последовательно (это не зависит от suspend / non-suspend функций), если вы там асинхронщину не сделаете
2) то что оно будет последовательно я понял из предыдущего вашего ответа, а вот не могу понять когда именно определяется момент для саспенда корутины. Для логики приложения это не важно, но хотелось бы иметь полное представление
в функции для записи/чтения тоже есть код, который не работает конкретно с сетью/диском, а обычные циклы там, условия и тд
1. Почитайте про Continuation Passing Style 2. потом после прочтения нужно осмыслить что вызов саспенд функции, в некотором роде разрывает тело функции. и передает часть после suspend в виде так называемого Continuation отдельным параметром вглубь вызываемой функции. 3. в качестве упражнения предлагаю переписать код без suspend функций, а в явном виде переписать в стиле continuation passing style.
ох ты божечки-кошечки, понял, спасибо за такую наводку, буду разбираться
определяется тем, когда у вас длительная операция. Никто не мешает лонг-операцию делать не саспенд и вызывать из корутины. В общем я плохо объясняю, не думаю что смогу нормально объяснить. Это почти бесполезно если у вас всё в одном CoroutineContext (ну разве что обозначить, что операция лонгполл или что внутри есть саспенд функции). Лучший пример для этого можно подчерпать с ведра: fun ui() = withContext(Dispatchers.Main) { io() textView.setText("") } suspend fun io() = withContext(Dispatchers.IO) { delay(10000L) } В таком случае, Main диспатчер ждёт выполнения io функции на Dispatchers.IO и даёт возможность выполнятся где-то в другом месте. В консольных аппах типа вашего это почти бесполезно, но в случаях где есть UI / нужна синхронизация и так далее это удобно.
Для того, чтобы функцию возможно было приостановить, компилятор её перемалывает, превращая в конечный автомат. Под капотом эта функция получает дополнительный параметр и вызывается каждый раз, когда она логически продолжается после приостановки. Такое нельзя вызвать из любой функции, только из другого такого же автомата. Точкой входа в эту систему являются корутин билдеры (вот эти все ранблокинги, лончи и иже с ними). Так что это не прихоть разработчиков, это механика такая.
Приостановка будет сделана только в том случае, если она нужна. Это диспетчер решает. Оно может выполниться и без приостановки, единственное, в точках приостановки выполняется дополнительный код, помогающий поддерживать машинерию отмены корутин и всякое такое.
Обсуждают сегодня