February 17, 2020

Начинаем изучать корутины

raywenderlich.com

Если у вас есть опыт разработки Android приложений, вы вероятно знакомы с разными способами написания асинхронного кода. Например можно использовать Native approach(Нативный подход), с использованием Thread и Runnable.

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

Другой подход заключается в использовании сторонних библиотек для различного рода операций. К примеру: получение данных из сети, выполнение запросов к базе данных. Для этих случаев вы можете использовать коллбеки и получать результат работы, либо использовать observable streams как в случае с RxJava для того чтобы создавать поток из полученных данных и применять к нему различные операторы. Все эти библиотеки самостоятельно решают проблему работы с потоками и парралельным выполением поставляя вам результат работы методов. Это может породить callback hell в вашем коде. Если вы начнете использовать большое количество коллбеков. Либо сделает ваш код чрезвычайно сложным для понимания если вы используете RxJava. Переключиться с одного подхода на другой задача не из простых, так как вам придется переписать практически весь ваш код. Это усложняет еще тот факт что зачастую такой код не так просто прочитать. Если вы подумываете об этом, то sequential code(последовательный код) является возможным решением данной проблемы. Так как такой код выглядит более понятно для человека.

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

Все это легко понять и использовать. Но что если бы у вас была возможность писать асинхронный код который легко рефакторить, читать и к тому же он бы являлся последовательным(sequential). Это все возможно воплотить в реальность используя Kotlin Coroutines.

Kotlin Coroutines позволяют вам работать с асинхронным кодом как с обычным последовательным(sequential). Все это достигается с помощью концепта функций приостановки(suspend fun). Приостановка(suspension) означает что функция помеченная как suspended будет поставлена на паузу во время выполнения до получения результата выполнения. Как пример, вы можете написать такую функцию от которой зависит ваша бизнес логика. К примеру получение данных из базы данных. В момент вызова такой функции блок в котором находится эта функция(parent) будет приоcтановлен до момента завершения выполения данной функции.

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

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

У этого подхода есть ограничение. Вы не можете использовать suspendable функции вне других suspendable функций или корутин. Но в то же время это хорошо. Потому - что вы разделяете функции на те что могут быть приостановлены и те что нет.

К плюсам корутин можно отнести то что вы избегаете накладных расходов при работе с многопоточностью. А также что Корутины являются частью стандартной библиотеки Kotlin поддерживаемой компанией JetBrains и обширным комьюнити разработчиков.