Ko-iso
Это репозиторий ko-iso, который предоставляет ISO-коды стран и регионов в виде Kotlin-библиотеки. Полезен для работы с международными стандартами, например, при обработке страновых кодов в приложениях. Поддерживает ISO 3166-1 (страны) и 3166-2 (регионы).
https://github.com/jillesvangurp/ko-iso
✍️ @kotlin_lib
Это репозиторий ko-iso, который предоставляет ISO-коды стран и регионов в виде Kotlin-библиотеки. Полезен для работы с международными стандартами, например, при обработке страновых кодов в приложениях. Поддерживает ISO 3166-1 (страны) и 3166-2 (регионы).
https://github.com/jillesvangurp/ko-iso
✍️ @kotlin_lib
👍8
moko-resources — это библиотека для управления ресурсами (строки, изображения, цвета и т.д.) в Kotlin Multiplatform проекте. Она позволяет использовать ресурсы из общего кода
Основные возможности:
- Доступ к ресурсам из
- Поддержка string, string formatting, plurals, colors, images
- Генерация кода на основе
- Поддержка Android, iOS, desktop (JetBrains Compose)
Пример использования:
Поддержка платформ:
- ✅ Android
- ✅ iOS
- ✅ Desktop (Compose Multiplatform)
https://github.com/icerockdev/moko-resources
✍️ @kotlin_lib
commonMain
.Основные возможности:
- Доступ к ресурсам из
commonMain
- Поддержка string, string formatting, plurals, colors, images
- Генерация кода на основе
.xml/.strings
файлов- Поддержка Android, iOS, desktop (JetBrains Compose)
Пример использования:
val str = MR.strings.some_string.desc()
textView.text = str.localized()
Поддержка платформ:
- ✅ Android
- ✅ iOS
- ✅ Desktop (Compose Multiplatform)
https://github.com/icerockdev/moko-resources
✍️ @kotlin_lib
👍5
Открытие браузера по умолчанию на разных платформах
Иногда приложение должно открыть веб-страницу в браузере по умолчанию. Хотя это кажется простой задачей, реализация может различаться в зависимости от платформы. Давайте посмотрим, как справиться с этим в разных средах.
Kotlin Multiplatform
В многоплатформенных проектах (например, с использованием Kotlin Multiplatform) приходится учитывать реализацию для каждой целевой платформы. Один из подходов — использовать ожидания/реализации (
https://dev.to/tkuenneth/open-the-default-browser-across-platforms-3cbh
✍️ @kotlin_lib
Иногда приложение должно открыть веб-страницу в браузере по умолчанию. Хотя это кажется простой задачей, реализация может различаться в зависимости от платформы. Давайте посмотрим, как справиться с этим в разных средах.
Kotlin Multiplatform
В многоплатформенных проектах (например, с использованием Kotlin Multiplatform) приходится учитывать реализацию для каждой целевой платформы. Один из подходов — использовать ожидания/реализации (
expect/actual
), чтобы объявить функцию в общем коде и реализовать её отдельно для каждой платформы.https://dev.to/tkuenneth/open-the-default-browser-across-platforms-3cbh
✍️ @kotlin_lib
👍2
🧵 Kotlin Coroutines без макияжа: что скрывается под капотом
Когда вы запускаете корутину с помощью
🔄 Жизненный цикл корутины:
1. Создание — с помощью
2. Запуск — автоматически или через
3. Приостановка — при вызове
4. Возобновление — после завершения асинхронной операции.
5. Завершение — когда весь код выполнен или корутина отменена.
🧠 Что такое
📌 Пример:
Компилятор преобразует этот код в класс, который можно представить следующим образом:
Здесь
https://habr.com/ru/articles/882988/
✍️ @kotlin_lib
Когда вы запускаете корутину с помощью
launch
или async
, компилятор Kotlin создаёт специальный объект, реализующий интерфейс Continuation
. Этот объект содержит состояние выполнения корутины и позволяет ей приостанавливаться и возобновляться. Внутри него хранятся все локальные переменные и текущая точка выполнения.🔄 Жизненный цикл корутины:
1. Создание — с помощью
launch
или async
.2. Запуск — автоматически или через
start()
.3. Приостановка — при вызове
suspend
-функций, таких как delay()
или await()
.4. Возобновление — после завершения асинхронной операции.
5. Завершение — когда весь код выполнен или корутина отменена.
🧠 Что такое
Continuation
?Continuation
— это объект, представляющий состояние выполнения корутины. Он позволяет приостанавливать и возобновлять выполнение, сохраняя информацию о том, где именно корутина была приостановлена. Интерфейс Continuation
выглядит следующим образом:
interface Continuation<in T> {
val context: CoroutineContext
fun resumeWith(result: Result<T>)
}
📌 Пример:
suspend fun mySuspendFunction() {
println("Start")
delay(1000)
println("End")
}
launch {
mySuspendFunction()
}
Компилятор преобразует этот код в класс, который можно представить следующим образом:
class GeneratedContinuation extends SuspendLambda {
int label;
@Override
Object invokeSuspend(Object result) {
switch (label) {
case 0:
println("Start");
label = 1;
if (delay(1000, this) == COROUTINE_SUSPENDED)
return COROUTINE_SUSPENDED;
case 1:
println("End");
return Unit.INSTANCE;
}
throw new IllegalStateException();
}
}
Здесь
label
указывает на текущую точку выполнения внутри корутины. При каждом вызове suspend
-функции значение label
изменяется, чтобы указать, с какого места нужно продолжить выполнение после приостановки.https://habr.com/ru/articles/882988/
✍️ @kotlin_lib
👍5
Плавная миграция на Kotlin 2.1.0
Всем привет, меня зовут Эдуард, я Android Tech Lead в QIC digital hub[ссылка удалена мод.]. Сегодня я расскажу как совершить плавный переход на Kotlin 2.1.0, руководствуясь опытом своей команды.
https://habr.com/ru/articles/898048/
✍️ @kotlin_lib
Всем привет, меня зовут Эдуард, я Android Tech Lead в QIC digital hub[ссылка удалена мод.]. Сегодня я расскажу как совершить плавный переход на Kotlin 2.1.0, руководствуясь опытом своей команды.
https://habr.com/ru/articles/898048/
✍️ @kotlin_lib
👍1
💻Хотите научиться писать эффективные сетевые клиенты для iOS и разобраться в том, какие технологии лучше выбрать для SwiftUI?
📖На открытом вебинаре 22 апреля в 20:00 мск мы подробно разберем архитектуру приложений на SwiftUI и выбор сетевого клиента: что лучше — Alamofire, Moya или нативное решение? Мы также покажем, как интегрировать эти технологии с Combine и async-await.
📊Умение работать с сетевыми клиентами под SwiftUI — ключевой навык для iOS-разработчика.
👉Регистрируйтесь прямо сейчас и получите скидку на большое обучение «iOS Developer. Professional» по промокоду IOSPRO4: https://vk.cc/cKRMfx
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
📖На открытом вебинаре 22 апреля в 20:00 мск мы подробно разберем архитектуру приложений на SwiftUI и выбор сетевого клиента: что лучше — Alamofire, Moya или нативное решение? Мы также покажем, как интегрировать эти технологии с Combine и async-await.
📊Умение работать с сетевыми клиентами под SwiftUI — ключевой навык для iOS-разработчика.
👉Регистрируйтесь прямо сейчас и получите скидку на большое обучение «iOS Developer. Professional» по промокоду IOSPRO4: https://vk.cc/cKRMfx
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
👍1
🧨 equals()
в Kotlin: незаметная ловушка, которая бьёт по бизнес-логикеКогда
equals()
работает не так, как ты думаешь — начинается отладочный ад. Особенно, если ты используешь data class
и полагаешься на их auto-generated equals.Представь кейс: ты получаешь DTO из API и кладёшь его в
Set
, надеясь, что дубликаты не появятся. Но через минуту замечаешь, что одинаковые по сути объекты спокойно живут рядом. Почему?📌 Типичная ошибка — включать в
equals()/hashCode()
поля, которые не участвуют в "бизнесовой" идентичности объекта. Например:
data class Product(
val id: String,
val name: String,
val lastUpdated: Long // техническое поле
)
Добавь два продукта с одинаковым
id
, но разным lastUpdated
— и Set посчитает их разными.equals()
и hashCode()
, вручную указав, какие поля важны:
data class Product(
val id: String,
val name: String,
val lastUpdated: Long
) {
override fun equals(other: Any?) =
other is Product && other.id == id
override fun hashCode() = id.hashCode()
}
🔥 Если используешь
copy()
— помни, что он тащит все поля. И если ты потом сравниваешь объекты по equals()
, может случиться сюрприз.✅ Вывод: auto-generated
equals()
удобен, но не всегда безопасен. Если объект участвует в коллекциях, кэшах или логике сравнения — контролируй его равенство вручную.✍️ @kotlin_lib
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3
Объяснение отмены корутин в Kotlin
Kotlin корутины предоставляют удобный способ асинхронного программирования. Но с этим удобством приходит и необходимость понять, как работает отмена. Давайте разберемся, как именно происходит отмена корутин и что это означает для вашего кода.
Что происходит при отмене?
Когда
- Вызов
- Явная проверка
Пример:
Если вы вызовете
Отмена и finally
Пример отмены
Вывод:
Как видно,
Заключение
Понимание механизма отмены корутин — важная часть работы с асинхронным кодом в Kotlin. Отмена не означает мгновенное завершение — корутина завершится в точке отмены. Используйте
https://sam-cooper.medium.com/kotlin-coroutine-cancellation-explained-6a545c8da252
✍️ @kotlin_lib
Kotlin корутины предоставляют удобный способ асинхронного программирования. Но с этим удобством приходит и необходимость понять, как работает отмена. Давайте разберемся, как именно происходит отмена корутин и что это означает для вашего кода.
Что происходит при отмене?
Когда
Job
отменяется, он переводится в состояние "отменено", но фактически корутина не завершится мгновенно. Она завершится, когда достигнет "точки отмены" (cancellation point). Это может быть:- Вызов
delay
, yield
и других suspend-функций, проверяющих isActive
.- Явная проверка
coroutineContext.isActive
или вызов ensureActive()
.Пример:
launch {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
}
Если вы вызовете
cancel()
на этой корутине, она остановится только после следующего delay
.Отмена и finally
try/finally
блоки работают в корутинах, как и ожидалось. Однако, если вы используете delay
или другую suspend-функцию в finally
, она тоже может быть отменена. Чтобы избежать этого, используйте withContext(NonCancellable)
:
try {
// работа
} finally {
withContext(NonCancellable) {
// гарантированно выполнится
}
}
Пример отмены
val job = launch {
try {
repeat(1000) { i ->
println("Job: I'm sleeping $i ...")
delay(500L)
}
} finally {
println("Job: I'm running finally")
}
}
delay(1300L) // немного подождем
println("main: I'm tired of waiting!")
job.cancelAndJoin() // отмена и ожидание завершения
println("main: Now I can quit.")
Вывод:
Job: I'm sleeping 0 ...
Job: I'm sleeping 1 ...
Job: I'm sleeping 2 ...
main: I'm tired of waiting!
Job: I'm running finally
main: Now I can quit.
Как видно,
finally
выполнится при отмене, но если в нем будет suspend-функция — нужно быть осторожным.Заключение
Понимание механизма отмены корутин — важная часть работы с асинхронным кодом в Kotlin. Отмена не означает мгновенное завершение — корутина завершится в точке отмены. Используйте
NonCancellable
, если нужно завершить работу "честно", несмотря на отмену.https://sam-cooper.medium.com/kotlin-coroutine-cancellation-explained-6a545c8da252
✍️ @kotlin_lib
👍3
На открытом уроке «Облако в кармане: запускаем всю инфраструктуру для теста при сборке» от OTUS мы расскажем, как избежать ручных настроек и запусков. Вместо этого вы научитесь автоматизировать весь процесс с помощью Docker, DockerCompose и TestContainers, интегрируя их с Gradle.
Урок полезен для разработчиков на Kotlin и Java, которые работают с автотестами — интеграционными и end-to-end.
В ходе урока вы освоите:
▫️Автоматический запуск всей необходимой инфраструктуры для тестирования.
▫️Создание Docker-образов для тестов и деплоя.
▫️Разработку автотестов, которые поднимут ваши навыки на новый уровень.
Участники получат скидку на курс «Kotlin Backend Developer. Professional».
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
🚀 Подборка Telegram каналов для программистов
Системное администрирование, DevOps 📌
https://www.tgoop.com/bash_srv Bash Советы
https://www.tgoop.com/win_sysadmin Системный Администратор Windows
https://www.tgoop.com/sysadmin_girl Девочка Сисадмин
https://www.tgoop.com/srv_admin_linux Админские угодья
https://www.tgoop.com/linux_srv Типичный Сисадмин
https://www.tgoop.com/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://www.tgoop.com/linux_odmin Linux: Системный администратор
https://www.tgoop.com/devops_star DevOps Star (Звезда Девопса)
https://www.tgoop.com/i_linux Системный администратор
https://www.tgoop.com/linuxchmod Linux
https://www.tgoop.com/sys_adminos Системный Администратор
https://www.tgoop.com/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://www.tgoop.com/sysadminof Книги для админов, полезные материалы
https://www.tgoop.com/i_odmin Все для системного администратора
https://www.tgoop.com/i_odmin_book Библиотека Системного Администратора
https://www.tgoop.com/i_odmin_chat Чат системных администраторов
https://www.tgoop.com/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://www.tgoop.com/sysadminoff Новости Линукс Linux
1C разработка 📌
https://www.tgoop.com/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://www.tgoop.com/DevLab1C 1С:Предприятие 8
https://www.tgoop.com/razrab_1C 1C Разработчик
https://www.tgoop.com/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://www.tgoop.com/rabota1C_rus Вакансии для программистов 1С
Программирование C++📌
https://www.tgoop.com/cpp_lib Библиотека C/C++ разработчика
https://www.tgoop.com/cpp_knigi Книги для программистов C/C++
https://www.tgoop.com/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://www.tgoop.com/pythonofff Python академия.
https://www.tgoop.com/BookPython Библиотека Python разработчика
https://www.tgoop.com/python_real Python подборки на русском и английском
https://www.tgoop.com/python_360 Книги по Python
Java разработка 📌
https://www.tgoop.com/BookJava Библиотека Java разработчика
https://www.tgoop.com/java_360 Книги по Java Rus
https://www.tgoop.com/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://www.tgoop.com/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://www.tgoop.com/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://www.tgoop.com/developer_mobila Мобильная разработка
https://www.tgoop.com/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://www.tgoop.com/frontend_1 Подборки для frontend разработчиков
https://www.tgoop.com/frontend_sovet Frontend советы, примеры и практика!
https://www.tgoop.com/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://www.tgoop.com/game_devv Все о разработке игр
Библиотеки 📌
https://www.tgoop.com/book_for_dev Книги для программистов Rus
https://www.tgoop.com/programmist_of Книги по программированию
https://www.tgoop.com/proglb Библиотека программиста
https://www.tgoop.com/bfbook Книги для программистов
БигДата, машинное обучение 📌
https://www.tgoop.com/bigdata_1 Big Data, Machine Learning
Программирование 📌
https://www.tgoop.com/bookflow Лекции, видеоуроки, доклады с IT конференций
https://www.tgoop.com/rust_lib Полезный контент по программированию на Rust
https://www.tgoop.com/golang_lib Библиотека Go (Golang) разработчика
https://www.tgoop.com/itmozg Программисты, дизайнеры, новости из мира IT
https://www.tgoop.com/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://www.tgoop.com/nodejs_lib Подборки по Node js и все что с ним связано
https://www.tgoop.com/ruby_lib Библиотека Ruby программиста
https://www.tgoop.com/lifeproger Жизнь программиста. Авторский канал.
QA, тестирование 📌
https://www.tgoop.com/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://www.tgoop.com/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://www.tgoop.com/thehaking Канал о кибербезопасности
https://www.tgoop.com/xakep_2 Хакер Free
Книги, статьи для дизайнеров 📌
https://www.tgoop.com/ux_web Статьи, книги для дизайнеров
Математика 📌
https://www.tgoop.com/Pomatematike Канал по математике
https://www.tgoop.com/phis_mat Обучающие видео, книги по Физике и Математике
https://www.tgoop.com/matgeoru Математика | Геометрия | Логика
Excel лайфхак📌
https://www.tgoop.com/Excel_lifehack
https://www.tgoop.com/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://www.tgoop.com/sysadmin_rabota Системный Администратор
https://www.tgoop.com/progjob Вакансии в IT
Системное администрирование, DevOps 📌
https://www.tgoop.com/bash_srv Bash Советы
https://www.tgoop.com/win_sysadmin Системный Администратор Windows
https://www.tgoop.com/sysadmin_girl Девочка Сисадмин
https://www.tgoop.com/srv_admin_linux Админские угодья
https://www.tgoop.com/linux_srv Типичный Сисадмин
https://www.tgoop.com/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://www.tgoop.com/linux_odmin Linux: Системный администратор
https://www.tgoop.com/devops_star DevOps Star (Звезда Девопса)
https://www.tgoop.com/i_linux Системный администратор
https://www.tgoop.com/linuxchmod Linux
https://www.tgoop.com/sys_adminos Системный Администратор
https://www.tgoop.com/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://www.tgoop.com/sysadminof Книги для админов, полезные материалы
https://www.tgoop.com/i_odmin Все для системного администратора
https://www.tgoop.com/i_odmin_book Библиотека Системного Администратора
https://www.tgoop.com/i_odmin_chat Чат системных администраторов
https://www.tgoop.com/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://www.tgoop.com/sysadminoff Новости Линукс Linux
1C разработка 📌
https://www.tgoop.com/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://www.tgoop.com/DevLab1C 1С:Предприятие 8
https://www.tgoop.com/razrab_1C 1C Разработчик
https://www.tgoop.com/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://www.tgoop.com/rabota1C_rus Вакансии для программистов 1С
Программирование C++📌
https://www.tgoop.com/cpp_lib Библиотека C/C++ разработчика
https://www.tgoop.com/cpp_knigi Книги для программистов C/C++
https://www.tgoop.com/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://www.tgoop.com/pythonofff Python академия.
https://www.tgoop.com/BookPython Библиотека Python разработчика
https://www.tgoop.com/python_real Python подборки на русском и английском
https://www.tgoop.com/python_360 Книги по Python
Java разработка 📌
https://www.tgoop.com/BookJava Библиотека Java разработчика
https://www.tgoop.com/java_360 Книги по Java Rus
https://www.tgoop.com/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://www.tgoop.com/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://www.tgoop.com/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://www.tgoop.com/developer_mobila Мобильная разработка
https://www.tgoop.com/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://www.tgoop.com/frontend_1 Подборки для frontend разработчиков
https://www.tgoop.com/frontend_sovet Frontend советы, примеры и практика!
https://www.tgoop.com/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://www.tgoop.com/game_devv Все о разработке игр
Библиотеки 📌
https://www.tgoop.com/book_for_dev Книги для программистов Rus
https://www.tgoop.com/programmist_of Книги по программированию
https://www.tgoop.com/proglb Библиотека программиста
https://www.tgoop.com/bfbook Книги для программистов
БигДата, машинное обучение 📌
https://www.tgoop.com/bigdata_1 Big Data, Machine Learning
Программирование 📌
https://www.tgoop.com/bookflow Лекции, видеоуроки, доклады с IT конференций
https://www.tgoop.com/rust_lib Полезный контент по программированию на Rust
https://www.tgoop.com/golang_lib Библиотека Go (Golang) разработчика
https://www.tgoop.com/itmozg Программисты, дизайнеры, новости из мира IT
https://www.tgoop.com/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://www.tgoop.com/nodejs_lib Подборки по Node js и все что с ним связано
https://www.tgoop.com/ruby_lib Библиотека Ruby программиста
https://www.tgoop.com/lifeproger Жизнь программиста. Авторский канал.
QA, тестирование 📌
https://www.tgoop.com/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://www.tgoop.com/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://www.tgoop.com/thehaking Канал о кибербезопасности
https://www.tgoop.com/xakep_2 Хакер Free
Книги, статьи для дизайнеров 📌
https://www.tgoop.com/ux_web Статьи, книги для дизайнеров
Математика 📌
https://www.tgoop.com/Pomatematike Канал по математике
https://www.tgoop.com/phis_mat Обучающие видео, книги по Физике и Математике
https://www.tgoop.com/matgeoru Математика | Геометрия | Логика
Excel лайфхак📌
https://www.tgoop.com/Excel_lifehack
https://www.tgoop.com/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://www.tgoop.com/sysadmin_rabota Системный Администратор
https://www.tgoop.com/progjob Вакансии в IT
Telegram
Bash Советы
🚀 Секреты и советы по Bash
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
💻 Прокачивай терминал вместе с нами! 👇
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
💻 Прокачивай терминал вместе с нами! 👇
Media is too big
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Ktor Server Fundemantals. Часть 1
Освойте разработку бэкенда на Ktor с использованием Kotlin! Эта серия материалов охватывает основы Ktor, маршрутизацию, обработку запросов, аутентификацию и другие ключевые концепции, которые помогут вам эффективно создавать надежные серверные приложения.
источник
✍️ @kotlin_lib
Освойте разработку бэкенда на Ktor с использованием Kotlin! Эта серия материалов охватывает основы Ktor, маршрутизацию, обработку запросов, аутентификацию и другие ключевые концепции, которые помогут вам эффективно создавать надежные серверные приложения.
источник
✍️ @kotlin_lib
👍5