Media is too big
VIEW IN TELEGRAM
Однопоточные корутины в Kotlin
Причина, по которой многим разработчикам сложно разобраться с корутинами в Kotlin, заключается не в том, что они сами по себе трудны для понимания. Проблема в том, что корутины часто подаются слишком перегруженно — сразу с погружением в асинхронный код. Но по своей сути корутины — это не про асинхронность. Это про конкурентное (параллельное) выполнение кода. И вот это как раз гораздо проще понять.
источник
✍️ @kotlin_lib
Причина, по которой многим разработчикам сложно разобраться с корутинами в Kotlin, заключается не в том, что они сами по себе трудны для понимания. Проблема в том, что корутины часто подаются слишком перегруженно — сразу с погружением в асинхронный код. Но по своей сути корутины — это не про асинхронность. Это про конкурентное (параллельное) выполнение кода. И вот это как раз гораздо проще понять.
источник
✍️ @kotlin_lib
👍5👎1
Media is too big
VIEW IN TELEGRAM
Алина Гребёнкина — как сделать так, чтобы разработчики использовали Kotlin
Тайм-коды:
00:00 — Избранные моменты выпуска
00:37 — Начало выпуска
00:50 — Расскажи подробнее, что ты делаешь на работе?
01:30 — Что такое Kotlin?
03:34 — Кем ты хотела стать, когда вырастешь?
05:10 — Про школу и интересы в школьное время
08:03 — Про ЕГЭ и обучение в СУНЦ НГУ
14:34 — Как ты выбирала универ и как тебе там было после СУНЦа?
16:45 — Как появилась твоя первая работа и что ты делала?
19:29 — Как происходил твой рост в работе за эти два года?
21:05 — Почему ты решила уйти и как искала новую работу?
23:00 — Про собеседования в Москве
24:21 — Работа в СММ-агентстве и переход к разработке брендинговых стратегий
26:33 — «Поняла, что хочется перейти на сторону продукта»
29:03 — Что ты делала в Bookmate?
31:22 — Почему ты ушла?
33:32 — Как ты попала в JetBrains?
37:55 — Что ты посоветуешь человеку, который хочет в IT?
40:45 — Ты работаешь в IT, но ты не пишешь код. Тебе с этим ок?
42:03 — Подкаст выходит при поддержке школы karpov.courses
42:27 — Cпасибо Haos Community Space за предоставленное место для съемки
источник
✍️ @kotlin_lib
Тайм-коды:
00:00 — Избранные моменты выпуска
00:37 — Начало выпуска
00:50 — Расскажи подробнее, что ты делаешь на работе?
01:30 — Что такое Kotlin?
03:34 — Кем ты хотела стать, когда вырастешь?
05:10 — Про школу и интересы в школьное время
08:03 — Про ЕГЭ и обучение в СУНЦ НГУ
14:34 — Как ты выбирала универ и как тебе там было после СУНЦа?
16:45 — Как появилась твоя первая работа и что ты делала?
19:29 — Как происходил твой рост в работе за эти два года?
21:05 — Почему ты решила уйти и как искала новую работу?
23:00 — Про собеседования в Москве
24:21 — Работа в СММ-агентстве и переход к разработке брендинговых стратегий
26:33 — «Поняла, что хочется перейти на сторону продукта»
29:03 — Что ты делала в Bookmate?
31:22 — Почему ты ушла?
33:32 — Как ты попала в JetBrains?
37:55 — Что ты посоветуешь человеку, который хочет в IT?
40:45 — Ты работаешь в IT, но ты не пишешь код. Тебе с этим ок?
42:03 — Подкаст выходит при поддержке школы karpov.courses
42:27 — Cпасибо Haos Community Space за предоставленное место для съемки
источник
✍️ @kotlin_lib
👍3❤1🤡1
🏆 Пройди тест из 10 вопросов, проверь свой уровень знаний и приходи учиться на онлайн-курс «Kotlin Backend Developer. Professional» от OTUS!
На курсе:
🎫 Курс можно приобрести в рассрочку
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
😁1💊1
Паттерн Декоратор в Kotlin — следуя принципу «Открытости/Закрытости»
В предыдущей статье мы рассмотрели принцип открытости/закрытости (Open/Closed Principle, OCP) — краеугольный камень SOLID, который гласит, что программные сущности должны быть открыты для расширения, но закрыты для модификации. Мы взяли жёсткую систему валидации одноразовых паролей (OTP) и переработали её с использованием паттерна «Стратегия», получив чистый и легко сопровождаемый код, где каждый набор правил валидации стал отдельным классом.
Это был огромный шаг вперёд. Но путь к действительно гибкой архитектуре редко заканчивается на первом решении. По мере усложнения требований ограничения одного паттерна часто подталкивают к применению другого.
https://itnext.io/decorator-pattern-in-kotlin-embracing-open-closed-principle-b469adc2ab7b
✍️ @kotlin_lib
В предыдущей статье мы рассмотрели принцип открытости/закрытости (Open/Closed Principle, OCP) — краеугольный камень SOLID, который гласит, что программные сущности должны быть открыты для расширения, но закрыты для модификации. Мы взяли жёсткую систему валидации одноразовых паролей (OTP) и переработали её с использованием паттерна «Стратегия», получив чистый и легко сопровождаемый код, где каждый набор правил валидации стал отдельным классом.
Это был огромный шаг вперёд. Но путь к действительно гибкой архитектуре редко заканчивается на первом решении. По мере усложнения требований ограничения одного паттерна часто подталкивают к применению другого.
https://itnext.io/decorator-pattern-in-kotlin-embracing-open-closed-principle-b469adc2ab7b
✍️ @kotlin_lib
👍3🤔1
Media is too big
VIEW IN TELEGRAM
Опыт внедрения Kotlin и Compose Multiplatform в продакшн-решение
Леонид Емельянов (SberAutoTech)
Поделюсь опытом перехода на Kotlin и Compose Multimplatform. Расскажу, почему мы выбрали именно эти решения, как переходили на новый технологический стек, являясь частью более крупного Android-приложения, и что из всего этого вышло.
источник
✍️ @kotlin_lib
Леонид Емельянов (SberAutoTech)
Поделюсь опытом перехода на Kotlin и Compose Multimplatform. Расскажу, почему мы выбрали именно эти решения, как переходили на новый технологический стек, являясь частью более крупного Android-приложения, и что из всего этого вышло.
источник
✍️ @kotlin_lib
👍1
🤖 Тест по Flutter проверь свои знания, готов ли ты к обучению на курсе.
Ответишь — пройдешь на курс "Flutter Mobile Developer" от OTUS по специальной цене + получишь доступ к записям открытых уроков курса
За 6 месяцев вы освоите Dart, Flutter и ключевые инструменты разработки, создадите несколько приложений, получите поддержку преподавателей и выполните проект для портфолио.
➡️ ПРОЙТИ ТЕСТ И ОЗНАКОМИТСЯ С ПРОГРАММОЙ: https://vk.cc/cO9FnG
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Ответишь — пройдешь на курс "Flutter Mobile Developer" от OTUS по специальной цене + получишь доступ к записям открытых уроков курса
За 6 месяцев вы освоите Dart, Flutter и ключевые инструменты разработки, создадите несколько приложений, получите поддержку преподавателей и выполните проект для портфолио.
➡️ ПРОЙТИ ТЕСТ И ОЗНАКОМИТСЯ С ПРОГРАММОЙ: https://vk.cc/cO9FnG
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Media is too big
VIEW IN TELEGRAM
Организация кода в проекте | В какой пакет положить Kotlin класс
0:00 Введение
1:16 Куда можно класть Kotlin файлы
2:42 Интеграция
3:39 Как разделить код по Gradle модулям
6:23 Несколько папок с исходным кодом
7:42 Пакеты с кодом
14:03 Выделение кода в AAR/JAR библиотеки
15:37 Заключение
источник
✍️ @kotlin_lib
0:00 Введение
1:16 Куда можно класть Kotlin файлы
2:42 Интеграция
3:39 Как разделить код по Gradle модулям
6:23 Несколько папок с исходным кодом
7:42 Пакеты с кодом
14:03 Выделение кода в AAR/JAR библиотеки
15:37 Заключение
источник
✍️ @kotlin_lib
👍1
Приглашаем на открытый урок, создадим приложение «Фото дня»
🗓 05 августа в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Android Developer. Professional».
На вебинаре:
- Разберемся с API сервера для скачивания фотографии и описания к ней
- Сверстаем простой экран для отображения данных
- Пропишем выход в интернет для скачивания данных
- Пропишем бизнес-логику для отображения данных на экране приложения
🔗 Ссылка на регистрацию: https://vk.cc/cO9GpJ
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👎1
Богатые ошибки в Kotlin | Михаил Зареченский
Модель null-безопасности в Kotlin — одна из её ключевых особенностей. В этом докладе мы рассмотрим, как эту модель можно обобщить до ограниченных объединённых типов, специально предназначенных для обработки ошибок.
Кроме того, мы обсудим, как ошибки могут быть представлены в Kotlin сегодня, включая такие подходы, как nullable-типы, исключения, иерархии sealed-классов и классы, подобные Result.
https://www.youtube.com/watch?v=IUrA3mDSWZQ
✍️ @kotlin_lib
Модель null-безопасности в Kotlin — одна из её ключевых особенностей. В этом докладе мы рассмотрим, как эту модель можно обобщить до ограниченных объединённых типов, специально предназначенных для обработки ошибок.
Кроме того, мы обсудим, как ошибки могут быть представлены в Kotlin сегодня, включая такие подходы, как nullable-типы, исключения, иерархии sealed-классов и классы, подобные Result.
https://www.youtube.com/watch?v=IUrA3mDSWZQ
✍️ @kotlin_lib
YouTube
Rich Errors in Kotlin | Michail Zarečenskij
Recording brought to you by American Express. https://americanexpress.io/kotlin-jobs
Kotlin's nullability model is one of its core features. In this talk, we’ll explore how this model can be generalized to restricted union types specifically designed for…
Kotlin's nullability model is one of its core features. In this talk, we’ll explore how this model can be generalized to restricted union types specifically designed for…
❤2👍1
Fuzz‑тестирование для Kotlin с помощью kotlinx.fuzz
Определение крайних (edge) случаев для тестирования — непростая задача, часто оставляющая скрытые баги и уязвимости незамеченными.
Fuzz‑тестирование (fuzzing) решает эту проблему, автоматически генерируя тесты со случайными или некорректными входными данными, что позволяет разработчикам выявлять неожиданные исключения и сценарии сбоев. Благодаря своей эффективности в обнаружении критических ошибок ПО, fuzzing получил широкое распространение во многих языках программирования.
Однако в Kotlin он остаётся сравнительно малоиспользуемым.
Именно поэтому наша Лаборатория языков программирования и анализа программ JetBrains Research посвятила усилия разработке kotlinx.fuzz — fuzzer’а для библиотек на Kotlin. Поскольку Kotlin компилируется в байткод JVM, системы fuzz‑тестирования для Kotlin можно строить, используя существующие Java‑fuzzer’ы.
Эта концепция и стала основой нашего текущего прототипа.
https://blog.jetbrains.com/research/2025/04/kotlinxfuzz-kotlin-fuzzing/
✍️ @kotlin_lib
Определение крайних (edge) случаев для тестирования — непростая задача, часто оставляющая скрытые баги и уязвимости незамеченными.
Fuzz‑тестирование (fuzzing) решает эту проблему, автоматически генерируя тесты со случайными или некорректными входными данными, что позволяет разработчикам выявлять неожиданные исключения и сценарии сбоев. Благодаря своей эффективности в обнаружении критических ошибок ПО, fuzzing получил широкое распространение во многих языках программирования.
Однако в Kotlin он остаётся сравнительно малоиспользуемым.
Именно поэтому наша Лаборатория языков программирования и анализа программ JetBrains Research посвятила усилия разработке kotlinx.fuzz — fuzzer’а для библиотек на Kotlin. Поскольку Kotlin компилируется в байткод JVM, системы fuzz‑тестирования для Kotlin можно строить, используя существующие Java‑fuzzer’ы.
Эта концепция и стала основой нашего текущего прототипа.
@KFuzzTest
fun testDuration(f: KFuzzer) {
val isoString = f.asciiString(10)
val duration = Duration.parseIsoStringOrNull(isoString)
println("$isoString -> $duration")
}
https://blog.jetbrains.com/research/2025/04/kotlinxfuzz-kotlin-fuzzing/
✍️ @kotlin_lib
👍2
Приглашаем на открытый урок который поможет решить эти вопросы.
🗓 12 августа в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Kotlin Backend Developer. Professional».
На открытом уроке «Почему все переходят на Kotlin? Секреты успешной миграции с Java» мы покажем, как сократить время разработки на 30% и минимизировать риски NullPointerException.
Вы узнаете ключевые отличия Kotlin, пошаговый план миграции без переписывания проекта и лучшие практики корутин для асинхронности.
🦾 Представьте, что каждый новый модуль пишется быстрее, ошибок становится в три раза меньше, а вы получаете бесценный навык для современных бэкенд-проектов.
🔗 Ссылка на регистрацию: https://vk.cc/cOhiMA
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
Избегайте использования изменяемых коллекций в конструкторе data-классов в Kotlin
В своих предыдущих статьях я показывал, как использование
Эти проблемы часто связаны с тем, как работают
https://proandroiddev.com/avoid-using-mutable-collections-in-the-data-class-constructor-in-kotlin-53d17897114e
✍️ @kotlin_lib
В своих предыдущих статьях я показывал, как использование
var
, Array
или лямбды в конструкторе data
-класса на Kotlin может привести к неожиданному поведению и трудноуловимым багам.Эти проблемы часто связаны с тем, как работают
equals()
, hashCode()
и copy()
— особенно в логике сравнения коллекций, диффов или рекомпозиции.https://proandroiddev.com/avoid-using-mutable-collections-in-the-data-class-constructor-in-kotlin-53d17897114e
✍️ @kotlin_lib
👍1
Тёмные стороны
Конструкции
Однако неправильное их использование может привести к следующим проблемам:
- Повреждённые stack trace’ы, из-за чего краши трудно отлаживать в продакшене.
- Тонкие баги с отменой корутин или
- Непреднамеренные утечки API и жёсткая связка встроенного (inlined) кода.
https://proandroiddev.com/the-dark-corners-of-inline-crossinline-and-reified-in-kotlin-d244eaa07bb1
✍️ @kotlin_lib
inline
, crossinline
и reified
в KotlinКонструкции
inline
, crossinline
и reified
в Kotlin позиционируются как абстракции без накладных расходов. Действительно, они позволяют избежать лишних выделений памяти, создавать типобезопасные билдеры и улучшать производительность.Однако неправильное их использование может привести к следующим проблемам:
- Повреждённые stack trace’ы, из-за чего краши трудно отлаживать в продакшене.
- Тонкие баги с отменой корутин или
IllegalStateException
.- Непреднамеренные утечки API и жёсткая связка встроенного (inlined) кода.
https://proandroiddev.com/the-dark-corners-of-inline-crossinline-and-reified-in-kotlin-d244eaa07bb1
✍️ @kotlin_lib
👍3
👩💻 Как создать свой собственный оператор Flow и использовать его в архитектуре приложения?
🗓 12 августа в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Android Developer. Professional».
На открытом уроке вы научитесь писать свой собственный оператор Flow с нуля. Мы разберём, как интегрировать оператор в архитектуру приложения, а также научимся строить архитектуру для гибкости и масштабируемости.
Этот урок идеально подойдёт разработчикам уровня junior и выше, стремящимся углубить знания и научиться эффективно использовать Flow в своих проектах.
🔗 Ссылка на регистрацию: https://vk.cc/cOkVjY
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🗓 12 августа в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Android Developer. Professional».
На открытом уроке вы научитесь писать свой собственный оператор Flow с нуля. Мы разберём, как интегрировать оператор в архитектуру приложения, а также научимся строить архитектуру для гибкости и масштабируемости.
Этот урок идеально подойдёт разработчикам уровня junior и выше, стремящимся углубить знания и научиться эффективно использовать Flow в своих проектах.
🔗 Ссылка на регистрацию: https://vk.cc/cOkVjY
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
👎1
Доклады с Droidcon New York 2025
https://www.youtube.com/playlist?list=PL9Pfzam3fFddgz_RF1T_NxlsGGo_9gfGN
✍️ @kotlin_lib
https://www.youtube.com/playlist?list=PL9Pfzam3fFddgz_RF1T_NxlsGGo_9gfGN
✍️ @kotlin_lib
👍2
Java vs Kotlin: у кого больше преимуществ в 2025 году
В 2018 я впервые познакомился с Kotlin, и он мне практически сразу понравился. Да и как можно не полюбить язык, названный в честь тотемного животного всех программистов? Шучу, на самом деле в честь острова.
Я уже несколько лет пишу бэкенд на Kotlin. До этого писал на Java, но переход совершил практически одномоментно, потому что тогда мне казалось, что Kotlin закрывает множество минусов Java и привносит более простой и лаконичный синтаксис. Но при этом я стараюсь следить за тем, как развивается Java.
https://habr.com/ru/companies/raiffeisenbank/articles/934990/
✍️ @kotlin_lib
В 2018 я впервые познакомился с Kotlin, и он мне практически сразу понравился. Да и как можно не полюбить язык, названный в честь тотемного животного всех программистов? Шучу, на самом деле в честь острова.
Я уже несколько лет пишу бэкенд на Kotlin. До этого писал на Java, но переход совершил практически одномоментно, потому что тогда мне казалось, что Kotlin закрывает множество минусов Java и привносит более простой и лаконичный синтаксис. Но при этом я стараюсь следить за тем, как развивается Java.
https://habr.com/ru/companies/raiffeisenbank/articles/934990/
✍️ @kotlin_lib
👎2👍1
🔥 Нововведения Kotlin 1.9-2.2 для JVM
Приглашаем на открытый урок.
🗓 19 августа в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Kotlin Backend Developer. Professional».
На вебинаре мы рассмотрим:
- изменения в enum
- data objects и data class
- JvmDefault
- компилятор K2
- guard conditions
- break and continue в лямбдах
- multi-dollar string interpolation
- context parameters
- context-sensitive resolution
- @ all
🔗 Ссылка на регистрацию: https://vk.cc/cOvnqv
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Приглашаем на открытый урок.
🗓 19 августа в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Kotlin Backend Developer. Professional».
На вебинаре мы рассмотрим:
- изменения в enum
- data objects и data class
- JvmDefault
- компилятор K2
- guard conditions
- break and continue в лямбдах
- multi-dollar string interpolation
- context parameters
- context-sensitive resolution
- @ all
🔗 Ссылка на регистрацию: https://vk.cc/cOvnqv
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Создание WebView-контрола для Compose Desktop
В компании TeamDev мы занимаемся разработкой JxBrowser — коммерческой библиотеки, которая позволяет встраивать Chromium-движок в Java-приложения на десктопах. Ранее нами уже были реализованы контролы
Что такое WebView внутри приложения
WebView — это UI-компонент, позволяющий приложению отображать и взаимодействовать с веб-контентом (вроде браузера внутри вашего приложения). Он отображает веб-страницы, обрабатывает JavaScript, куки и другие веб-взаимодействия — полностью в рамках жизненного цикла приложения.
Зачем Compose
Jetpack Compose быстро стал популярен среди Kotlin-разработчиков на Android. Compose Multiplatform расширяет этот подход на десктоп. Однако у Compose нет встроенного десктопного WebView — и мы увидели отличную возможность закрыть этот пробел.
Новая модель UI
Compose использует декларативный подход: UI описывается состоянием, вместо императивного обновления элементов. Компонент отображает текущее состояние, и изменения происходят автоматически по мере смены состояния.
Основная техническая задача: рендеринг
Chromium рендерит страницу в отдельном процессе, а затем результат — пиксели — нужно передать обратно Java/Kotlin для отображения внутри Compose. Мы решили это двумя способами:
1. Копирование пикселей — Chromium рендерит страницу, копирует пиксели в Java-буфер, и затем изображение рисуется в Compose
2. Рендеринг на нативной поверхности — более производительно: Chromium отрисовывает контент напрямую на нативной поверхности, встроенной в Compose.
https://teamdev.com/jxbrowser/blog/building-web-view-for-compose/
✍️ @kotlin_lib
В компании TeamDev мы занимаемся разработкой JxBrowser — коммерческой библиотеки, которая позволяет встраивать Chromium-движок в Java-приложения на десктопах. Ранее нами уже были реализованы контролы
BrowserView
для классических Java GUI-фреймворков: Swing, JavaFX и SWT. Теперь мы решили расширить поддержку и создать аналогичный компонент для Compose Multiplatform — для Desktop.Что такое WebView внутри приложения
WebView — это UI-компонент, позволяющий приложению отображать и взаимодействовать с веб-контентом (вроде браузера внутри вашего приложения). Он отображает веб-страницы, обрабатывает JavaScript, куки и другие веб-взаимодействия — полностью в рамках жизненного цикла приложения.
Зачем Compose
Jetpack Compose быстро стал популярен среди Kotlin-разработчиков на Android. Compose Multiplatform расширяет этот подход на десктоп. Однако у Compose нет встроенного десктопного WebView — и мы увидели отличную возможность закрыть этот пробел.
Новая модель UI
Compose использует декларативный подход: UI описывается состоянием, вместо императивного обновления элементов. Компонент отображает текущее состояние, и изменения происходят автоматически по мере смены состояния.
Основная техническая задача: рендеринг
Chromium рендерит страницу в отдельном процессе, а затем результат — пиксели — нужно передать обратно Java/Kotlin для отображения внутри Compose. Мы решили это двумя способами:
1. Копирование пикселей — Chromium рендерит страницу, копирует пиксели в Java-буфер, и затем изображение рисуется в Compose
Canvas
.2. Рендеринг на нативной поверхности — более производительно: Chromium отрисовывает контент напрямую на нативной поверхности, встроенной в Compose.
https://teamdev.com/jxbrowser/blog/building-web-view-for-compose/
✍️ @kotlin_lib
👍3
Разница между job.cancel() и scope.cancel() в Kotlin Coroutines
В Kotlin-корутинах часто путают отмену конкретного
Что такое Job и Scope?
-
-
Отменяет только одну корутину.
Scope остаётся активным и можно запускать новые задачи.
Отменяет все корутины в области видимости и сам scope.
После этого новые корутины запустить уже нельзя.
https://medium.com/proandroiddev/kotlin-coroutines-the-real-difference-between-job-cancel-and-scope-cancel-05e1d9dd5245
✍️ @kotlin_lib
В Kotlin-корутинах часто путают отмену конкретного
Job
и всей области видимости (Scope
). Разберёмся.Что такое Job и Scope?
-
Job
- отдельная корутина, возвращается при launch
или async
.-
CoroutineScope
- контейнер для корутин. В нём есть общий Job
, управляющий жизненным циклом всех корутин внутри.job.cancel()
Отменяет только одну корутину.
val scope = CoroutineScope(Dispatchers.Default)
val jobA = scope.launch { delay(5000) }
val jobB = scope.launch { delay(10000) }
jobA.cancel() // Отменится только jobA, jobB продолжит работу
Scope остаётся активным и можно запускать новые задачи.
scope.cancel()
Отменяет все корутины в области видимости и сам scope.
scope.cancel() // Все корутины в scope будут остановлены
После этого новые корутины запустить уже нельзя.
https://medium.com/proandroiddev/kotlin-coroutines-the-real-difference-between-job-cancel-and-scope-cancel-05e1d9dd5245
✍️ @kotlin_lib
👍5
🦾 Ответишь — пройдешь на продвинутый курс "Android Developer. Professional " от OTUS.
За 5 месяцев обучения ты освоишь:
👉 ПРОЙТИ ТЕСТ: https://vk.cc/cOz4d1
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM