Forwarded from Android Broadcast
Алексей Панов @kotlin_adept , опытный мобильный разработчик, реализующий приложения с применением KMP, проведет собеседование на позицию Kotlin Multiplatform разработчика в прямом эфире на YouTube канале "Android Broadcast" (время и дата будут объявлены позже)
Требования к кандидату:
👉 Опыт в мобильной разработки
👉 Опыт с Kotlin
👉 Понимание как происходит разработка приложений с KMP
Будет теория и практика. Это ваш шанс проявить себя и заявить на большую аудиторию о своих возможностях!
Если решили принять участие - заполняйте анкету!
#AndroidBroadcast
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👎2
Проблема версионирования
Продолжаем тему KMP, и прежде чем перейти к следующей проблеме, хочется поговорить о том, как мы делим наши библиотеки для предоставления общего кода в iOS.
Мы разбиваем библиотеку на две части: core и compose. В core-модуле, соответственно, лежит вся логика, а в compose — только вёрстка. При этом каждый модуль мы делим на пакеты api/internal и с помощью правила detekt запрещаем использовать публичные сущности из пакета internal.
Также мы стараемся избегать использования сторонних библиотек, кроме ключевых, таких, как Ktor, SQLDelight, но в качестве исключения мы приняли решение использовать Decompose. Это позволяет значительно упростить интеграцию с общим кодом в iOS, ведь всё, что нужно сделать — это смаппить жизненный цикл. А дальше, в зависимости от текущего состояния навигации, показываем тот или иной экран и отправляем события в компонент. Это позволяет скрыть все детали реализации и меньше страдать из-за проблем с интеропом.
Однако то, что хорошо работает на iOS, создаёт проблемы на Android, так как в публичном интерфейсе core-модуля приходится раскрывать все интерфейсы компонентов, чтобы иметь возможность обращаться к ним из ui-модуля. Хотя для интеграции модуля в Android достаточно передать верхнеуровневый компонент из core-модуля в экран, никто не мешает разработчикам обращаться к другим публичным сущностям.
Одним из решений здесь видится использование специальных аннотаций, например
В такой парадигме поддерживать обратную совместимость API, а тем более ABI, почти нереально. Поэтому, поскольку это внутренние библиотеки, мы приняли решение поднимать мажорную версию только в том случае, если реально ломаем точки интеграции API. Для iOS мы просто создаём задачи на доработку, где указываем, что поменялось в этом релизе и что требует обновления.
Процесс получился далёким от идеала, но пока что это работает🙃
#KMP #iOS
Продолжаем тему KMP, и прежде чем перейти к следующей проблеме, хочется поговорить о том, как мы делим наши библиотеки для предоставления общего кода в iOS.
Мы разбиваем библиотеку на две части: core и compose. В core-модуле, соответственно, лежит вся логика, а в compose — только вёрстка. При этом каждый модуль мы делим на пакеты api/internal и с помощью правила detekt запрещаем использовать публичные сущности из пакета internal.
Также мы стараемся избегать использования сторонних библиотек, кроме ключевых, таких, как Ktor, SQLDelight, но в качестве исключения мы приняли решение использовать Decompose. Это позволяет значительно упростить интеграцию с общим кодом в iOS, ведь всё, что нужно сделать — это смаппить жизненный цикл. А дальше, в зависимости от текущего состояния навигации, показываем тот или иной экран и отправляем события в компонент. Это позволяет скрыть все детали реализации и меньше страдать из-за проблем с интеропом.
Однако то, что хорошо работает на iOS, создаёт проблемы на Android, так как в публичном интерфейсе core-модуля приходится раскрывать все интерфейсы компонентов, чтобы иметь возможность обращаться к ним из ui-модуля. Хотя для интеграции модуля в Android достаточно передать верхнеуровневый компонент из core-модуля в экран, никто не мешает разработчикам обращаться к другим публичным сущностям.
Одним из решений здесь видится использование специальных аннотаций, например
@InternalVisibilityAPI, которые будут предупреждать пользователя о том, что это внутренний API библиотеки.В такой парадигме поддерживать обратную совместимость API, а тем более ABI, почти нереально. Поэтому, поскольку это внутренние библиотеки, мы приняли решение поднимать мажорную версию только в том случае, если реально ломаем точки интеграции API. Для iOS мы просто создаём задачи на доработку, где указываем, что поменялось в этом релизе и что требует обновления.
Процесс получился далёким от идеала, но пока что это работает
#KMP #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👍28❤2
Это уже мое четвертое публичное собеседование, в котором я стараюсь раскрыть основные аспекты работы с современными технологиями:
Сегодня на собеседовании будет задачка на ревью проекта с плохим кодом, но с упором на KMP. И по ходу эфира обсудим все нюансы интеграции общего кода с iOS.
Если вам интересна эта тема, обязательно приходите на прямой эфир, будет интересно! А в конце я смогу ответить на все ваши вопросы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥48❤3🤡3
Материалы для углублённого изучения KMP
По мотивам вчерашнего собеса хочу посоветовать классные доклады, которые помогут вам глубже разобраться в принципах работы Kotlin Multiplatform и Kotlin Native, а также лучше понять нюансы интеропа со Swift-кодом.
На английском:
🔘 ЖЦ объектов в Kotlin/Native
🔘 Процесс компиляции в Kotlin/Native, отличия статических и динамических фреймворков
🔘 Проблемы текущего интеропа и возможные пути улучшения
🔘 Разница между Kotlin и Swift concurrency
🔘 Принцип работы Swift Export
На русском:
🔘 Совместная работа Kotlin/Native GC и ARC в Swift
🔘 iOS Memory Management
#KMP
По мотивам вчерашнего собеса хочу посоветовать классные доклады, которые помогут вам глубже разобраться в принципах работы Kotlin Multiplatform и Kotlin Native, а также лучше понять нюансы интеропа со Swift-кодом.
На английском:
На русском:
#KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29🔥14😁1
Стоит ли переходить с Room на SQLDelight?
На данный момент обе библиотеки поддерживают KMP. Если раньше особого выбора не было, то теперь многие могут задаться вопросом: стоит ли вообще переходить с Room?
Я считаю, что нет, не стоит. Конечно, у каждой библиотеки есть свои преимущества и недостатки, но, на мой взгляд, у SQLDelight их заметно больше:
🔘 Нельзя задать разные имена для таблицы в БД и сгенерированного класса. Если вы придерживаетесь общепринятого синтаксиса именования таблиц, то имена сгенерированных классов будут выглядеть просто ужасно.
🔘 Видимость сгенерированных файлов также нельзя регулировать — все они будут public.
🔘 Нет поддержки suspend-функций, приходится явно менять диспетчер для каждого запроса. (оказывается есть, в настройках плагина есть свойство generateAsync)
🔘 Нельзя сразу сгенерировать класс с отношением many-to-many или другими связями, например, чтобы получить фильм со списком актёров, придётся делать дополнительный маппинг на стороне Kotlin.
🔘 Нет автоматических миграций, как в Room (но в целом это зло).
🔘 Очень скудная документация.
Из плюсов я бы выделил следующее:
🟢 Небольшие таблицы можно сразу смаппить в доменные типы с помощью Type Projections.
🟢 Нет магии аннотаций, все запросы пишутся явно.
🟢 Нет зависимости на KSP и плагины компилятора.
🟢 Поддерживается больше таргетов, чем в Room.
🟢 Может работать не только с SQLite.
В общем, я пришёл к выводу, что Room для меня выигрывает у SQLDelight, и мигрировать с него я бы не стал. Но и возвращаться обратно, если вы уже перешли, особого смысла тоже не вижу.
А что думаете вы, какая из библиотек вам ближе❓
#Room #SQLDelight #KMP
На данный момент обе библиотеки поддерживают KMP. Если раньше особого выбора не было, то теперь многие могут задаться вопросом: стоит ли вообще переходить с Room?
Я считаю, что нет, не стоит. Конечно, у каждой библиотеки есть свои преимущества и недостатки, но, на мой взгляд, у SQLDelight их заметно больше:
Из плюсов я бы выделил следующее:
В общем, я пришёл к выводу, что Room для меня выигрывает у SQLDelight, и мигрировать с него я бы не стал. Но и возвращаться обратно, если вы уже перешли, особого смысла тоже не вижу.
А что думаете вы, какая из библиотек вам ближе
#Room #SQLDelight #KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
❤25👍12❤🔥3
10 кругов ада, или как вручную перенести все фотки из-за аккаунта разработчика
Так вышло, что фотографирую я не очень часто, и только сейчас у меня закончилось место на Google Диске. Теперь в каждом своём приложении Google показывает страшные баннеры и вынуждает купить подписку🤑
Что ж, убедили, идём покупать. Но с русским платёжным профилем ничего не купить. Зачем тогда предлагали? Ну да ладно.
Пытаемся поменять платёжный профиль, но этого сделать нельзя из-за активного аккаунта разработчика🤨
Аккаунт я давно забросил и все приложения там удалил, но Google заодно «удалил» и мой аккаунт, так как я не подтвердил личность.
Пишу в техподдержку, чтобы аккаунт удалили окончательно и я смог поменять платёжный профиль. На что получаю ответ: сделать это нельзя, если на аккаунте нет активных приложений😵
Тут я понял, что ситуация патовая и надо что-то делать. Одним из вариантов было создать новый аккаунт для фоток и заодно перенести все фото на Яндекс Диск.
Окей, качаем через Google Takeout архив со всеми фотками. Метаданные EXIF лежат там в отдельном JSON-файле, соответственно, ни данных о дате, ни геолокации в фотке нет, и нужно это как-то восстанавливать.
Я нашёл скрипт на Python, который это делает, и пришлось ещё немного подвайбкодить, чтобы всё заработало...
Вот такой вот квест получился. А если бы аккаунта разработчика не было, все бы решилось проще, так что думайте😏
#Offtop
Так вышло, что фотографирую я не очень часто, и только сейчас у меня закончилось место на Google Диске. Теперь в каждом своём приложении Google показывает страшные баннеры и вынуждает купить подписку
Что ж, убедили, идём покупать. Но с русским платёжным профилем ничего не купить. Зачем тогда предлагали? Ну да ладно.
Пытаемся поменять платёжный профиль, но этого сделать нельзя из-за активного аккаунта разработчика
Аккаунт я давно забросил и все приложения там удалил, но Google заодно «удалил» и мой аккаунт, так как я не подтвердил личность.
Пишу в техподдержку, чтобы аккаунт удалили окончательно и я смог поменять платёжный профиль. На что получаю ответ: сделать это нельзя, если на аккаунте нет активных приложений
Тут я понял, что ситуация патовая и надо что-то делать. Одним из вариантов было создать новый аккаунт для фоток и заодно перенести все фото на Яндекс Диск.
Окей, качаем через Google Takeout архив со всеми фотками. Метаданные EXIF лежат там в отдельном JSON-файле, соответственно, ни данных о дате, ни геолокации в фотке нет, и нужно это как-то восстанавливать.
Я нашёл скрипт на Python, который это делает, и пришлось ещё немного подвайбкодить, чтобы всё заработало...
Вот такой вот квест получился. А если бы аккаунта разработчика не было, все бы решилось проще, так что думайте
#Offtop
Please open Telegram to view this post
VIEW IN TELEGRAM
1🤯22😁8❤3👍1😨1
Зоопарк кроссплатформенных фреймворков
Думаю, вы все слышали про такие фреймворки, как Flutter и Expo (React Native) для разработки кроссплатформенных мобильных приложений и не только. Но, разумеется, таких фреймворков существует значительно больше, и по сей день появляются новые решения.
Давайте рассмотрим некоторые из них:
Valdi — фреймворк от Snapchat, где UI пишется на TypeScript DSL, который напрямую компилируется в нативные вьюшки. Разработчики обещают производительность, сопоставимую с нативными приложениями, так как фреймворк не использует ни WebView, ни JavaScript Bridge. Поддерживает Android, iOS и macOS.
ArkUI-X — проект, расширяющий декларативный UI-фреймворк для разработки приложений под HarmonyOS NEXT и позволяющий добавить поддержку компиляции под Android и iOS. Это ещё один фреймворк, использующий TypeScript, а точнее его надмножество ArkTS.
Skip — единственный платный для корпоративного использования фреймворк, который изначально представлял собой транспилятор из Swift в Kotlin и позволял переводить нативные iOS-приложения на SwiftUI в Android-приложения с Jetpack Compose. Но в новом режиме Fuse Skip начал использовать недавно вышедший Swift SDK для Android, что позволит уйти от прямой транспиляции кода по крайней мере для бизнес-логики.
Если честно, я не верю в широкое распространение этих фреймворков, но будет интересно посмотреть, к чему всё это приведёт. А что думаете вы? Попробовали бы один из этих фреймворков для разработки мобильных приложений?
#Crossplatform #Frameworks
Думаю, вы все слышали про такие фреймворки, как Flutter и Expo (React Native) для разработки кроссплатформенных мобильных приложений и не только. Но, разумеется, таких фреймворков существует значительно больше, и по сей день появляются новые решения.
Давайте рассмотрим некоторые из них:
Valdi — фреймворк от Snapchat, где UI пишется на TypeScript DSL, который напрямую компилируется в нативные вьюшки. Разработчики обещают производительность, сопоставимую с нативными приложениями, так как фреймворк не использует ни WebView, ни JavaScript Bridge. Поддерживает Android, iOS и macOS.
ArkUI-X — проект, расширяющий декларативный UI-фреймворк для разработки приложений под HarmonyOS NEXT и позволяющий добавить поддержку компиляции под Android и iOS. Это ещё один фреймворк, использующий TypeScript, а точнее его надмножество ArkTS.
Skip — единственный платный для корпоративного использования фреймворк, который изначально представлял собой транспилятор из Swift в Kotlin и позволял переводить нативные iOS-приложения на SwiftUI в Android-приложения с Jetpack Compose. Но в новом режиме Fuse Skip начал использовать недавно вышедший Swift SDK для Android, что позволит уйти от прямой транспиляции кода по крайней мере для бизнес-логики.
Если честно, я не верю в широкое распространение этих фреймворков, но будет интересно посмотреть, к чему всё это приведёт. А что думаете вы? Попробовали бы один из этих фреймворков для разработки мобильных приложений?
#Crossplatform #Frameworks
👍12😐7
Как улучшить дальность сканирования кодов маркировки
Библиотеки вроде Google ML Kit, ZXing или его аналога на C++ со стандартными настройками камеры имеют довольно посредственную дальность сканирования, приходится подносить камеру очень близко, чтобы хоть что-то отсканировать. Особенно это касается акцизных марок нового образца. При этом, если взглянуть на коммерческие решения, они работают на голову выше.
Как можно улучшить ситуацию?
🟢 Как ни странно, можно попробовать уменьшить разрешение камеры, двух мегапикселей более чем достаточно для распознавания.
🟢 Увеличить параметр zoomRatio в камере по-умолчанию, например, установить 1.5f вместо 1f.
🟢 Реализовать автоматический зум к потенциальным кодам. Для этого в ML Kit появились настройки enableAllPotentialBarcodes и ZoomSuggestionOptions.
🟢 Ограничить размер зоны сканирования.
Наверняка можно придумать что-то ещё. Хотелось бы спросить совета у тех, кто уже сталкивался с подобной задачей, есть идеи, что еще можно сделать?
P.S. Обучение собственной модели не предлагать🙂
#Camera #BarcodeReader
Библиотеки вроде Google ML Kit, ZXing или его аналога на C++ со стандартными настройками камеры имеют довольно посредственную дальность сканирования, приходится подносить камеру очень близко, чтобы хоть что-то отсканировать. Особенно это касается акцизных марок нового образца. При этом, если взглянуть на коммерческие решения, они работают на голову выше.
Как можно улучшить ситуацию?
Наверняка можно придумать что-то ещё. Хотелось бы спросить совета у тех, кто уже сталкивался с подобной задачей, есть идеи, что еще можно сделать?
P.S. Обучение собственной модели не предлагать
#Camera #BarcodeReader
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21👍5❤🔥3😈1
Посмотрите на код на изображении. Эта composable-функция используется на экране с камерой, чтобы сделать полупрозрачную рамку по периметру. Как думаете, в чем тут проблема?
Вместо прозрачного выреза на некоторых старых устройствах будет чёрный прямоугольник.
Я уже когда-то сталкивался с этой проблемой, когда Compose еще не было и в помине. При работе с Android Canvas проблема заключалась в использовании PorterDuff.Mode.CLEAR.
В прошлый раз эту проблему в AndroidView удалось пофиксить, переведя отрисовку на hardware-accelerated layer:
Но как сделать то же самое в Compose? Если просто получить текущий View через LocalView, то, вероятно, мы не получим нужного поведения, так как изменим layerType для верхнеуровневой вьюшки.
Мне ничего лучше не пришло в голову, чем сделать composable-функцию враппер, в которой контент будет прокидываться в AbstractComposeView, где уже и будет происходить изменение layerType.
Таким образом, чтобы пофиксить проблему, достаточно будет обернуть код на изображении в этот враппер. Если нужен код враппера, напишите в комментариях.
P.S. Как думаете, когда люди уже перестанут использовать семилетние смартфоны Xiaomi?
#Android #Canvas #Compose
Я уже когда-то сталкивался с этой проблемой, когда Compose еще не было и в помине. При работе с Android Canvas проблема заключалась в использовании PorterDuff.Mode.CLEAR.
В прошлый раз эту проблему в AndroidView удалось пофиксить, переведя отрисовку на hardware-accelerated layer:
setLayerType(LAYER_TYPE_HARDWARE, null)
Но как сделать то же самое в Compose? Если просто получить текущий View через LocalView, то, вероятно, мы не получим нужного поведения, так как изменим layerType для верхнеуровневой вьюшки.
Мне ничего лучше не пришло в голову, чем сделать composable-функцию враппер, в которой контент будет прокидываться в AbstractComposeView, где уже и будет происходить изменение layerType.
Таким образом, чтобы пофиксить проблему, достаточно будет обернуть код на изображении в этот враппер. Если нужен код враппера, напишите в комментариях.
P.S. Как думаете, когда люди уже перестанут использовать семилетние смартфоны Xiaomi?
#Android #Canvas #Compose
🤯22🔥3😭3👍2
🔥 Уже понимаете, что Kotlin — это будущее автоматизации? Тогда не пропустите наш вебинар
24 ноября в 20:00 мск! Роман Сперанский расскажет, почему Kotlin — это ключ к быстрым, чистым и умным тестам, а также поделится практическими советами для вашего развития.
Регистрируйтесь по ссылке🔗
Хотите перейти к реальной практике и освоить автоматизацию на Kotlin?
Начинайте обучение сейчас и получите 5% скидку!
Онлайн-курс включает 22 занятия, домашние задания, живые вебинары, 100 часов практики и два проекта для портфолио — всё под руководством эксперта с 16-летним опытом.
Узнайте все детали курса на сайте🔗
24 ноября в 20:00 мск! Роман Сперанский расскажет, почему Kotlin — это ключ к быстрым, чистым и умным тестам, а также поделится практическими советами для вашего развития.
Регистрируйтесь по ссылке
Хотите перейти к реальной практике и освоить автоматизацию на Kotlin?
Начинайте обучение сейчас и получите 5% скидку!
Онлайн-курс включает 22 занятия, домашние задания, живые вебинары, 100 часов практики и два проекта для портфолио — всё под руководством эксперта с 16-летним опытом.
Узнайте все детали курса на сайте
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6👎4🤝1
Android Gradle Library Plugin
Если вы вдруг пропустили, то для KMP-проектов появился отдельный Android-плагин для library-модулей, который значительно уменьшает количество Gradle-тасок и ускоряет как конфигурацию проекта, так и сборку.
Особенности плагина:
🔘 В нём убрали поддержку flavor и build type.
🔘 Отключена Java-компиляция по умолчанию.
🔘 Отключены по умолчанию unit и инструментальные тесты (не забудьте про них, а то будет как в этом посте).
Мы уже подключили его в пару наших проектов, и результаты действительно впечатляющие🔥
🟢 Количество тасок при прогоне unit-тестов уменьшилось более чем в 4 раза, и во столько же раз удалось ускорить их выполнение.
🟢 С Android Lint похожая история: там количество запускаемых тасок сократилось в 2 раза, и в 1,5 раза удалось получить прирост скорости.
В общем, миграция определённо того стоит, но посмотрите внимательно на текущие ограничения в документации, возможно, вам пока этот плагин не подойдёт.
#Android #KMP #Gradle
Если вы вдруг пропустили, то для KMP-проектов появился отдельный Android-плагин для library-модулей, который значительно уменьшает количество Gradle-тасок и ускоряет как конфигурацию проекта, так и сборку.
Особенности плагина:
Мы уже подключили его в пару наших проектов, и результаты действительно впечатляющие
В общем, миграция определённо того стоит, но посмотрите внимательно на текущие ограничения в документации, возможно, вам пока этот плагин не подойдёт.
#Android #KMP #Gradle
Please open Telegram to view this post
VIEW IN TELEGRAM
👍24😱2
Jetpack Navigation 3
Только сейчас дошли руки более пристально взглянуть на новую Jetpack Navigation 3.
Помню, многие жаловались, что Decompose весь такой сложный, а навигация от Google простая. Но что мы видим в новой версии:
NavBackStack, NavEntry, NavDisplay, NavEntryDecorator, SceneStrategy и так далее🫠
При этом, несмотря на то что вышла стабильная версия, много кода всё равно придётся писать дополнительно:
Хочешь навигацию по табам? Пиши код для управления бэкстеком.
Нужен BottomSheet? Пиши декоратор.
Необходимо привязать ЖЦ ViewModel к экрану? Подключай отдельную библиотеку.
Нужна вложенная навигация? Разбирайся с кастомными сценами.
В общем, вы поняли. Довольно много бойлерплейта придётся копировать из примеров на GitHub, чтобы всё завести. Если хотите, чтобы я сделал подробное сравнение с Decompose, вы знаете, что надо сделать👍
Ну и напишите, планируете ли вы миграцию с любой другой библиотеки на Navigation 3? Интересно будет узнать ваше мнение.
#Compose #Navigation
Только сейчас дошли руки более пристально взглянуть на новую Jetpack Navigation 3.
Помню, многие жаловались, что Decompose весь такой сложный, а навигация от Google простая. Но что мы видим в новой версии:
NavBackStack, NavEntry, NavDisplay, NavEntryDecorator, SceneStrategy и так далее
При этом, несмотря на то что вышла стабильная версия, много кода всё равно придётся писать дополнительно:
Хочешь навигацию по табам? Пиши код для управления бэкстеком.
Нужен BottomSheet? Пиши декоратор.
Необходимо привязать ЖЦ ViewModel к экрану? Подключай отдельную библиотеку.
Нужна вложенная навигация? Разбирайся с кастомными сценами.
В общем, вы поняли. Довольно много бойлерплейта придётся копировать из примеров на GitHub, чтобы всё завести. Если хотите, чтобы я сделал подробное сравнение с Decompose, вы знаете, что надо сделать
Ну и напишите, планируете ли вы миграцию с любой другой библиотеки на Navigation 3? Интересно будет узнать ваше мнение.
#Compose #Navigation
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍97🔥14❤7🤯4
QA Mobile MeetUp
Если вы тестируете мобильные приложения, приходите на митап Спортса” и Selectel.
Обсудим насущное: сбор ферм девайсов, генерацию тестовых данных, ревью тест-кейсов и тестирование рекламы.
📍оффлайн в Москве и онлайн
🗓5 декабря, 18:00
👉 Смотрите программу и регистрируйтесь: https://sprts.cc/0ulpbs
Реклама. АО "Селектел". erid:2W5zFJSg6Ta
Если вы тестируете мобильные приложения, приходите на митап Спортса” и Selectel.
Обсудим насущное: сбор ферм девайсов, генерацию тестовых данных, ревью тест-кейсов и тестирование рекламы.
📍оффлайн в Москве и онлайн
🗓5 декабря, 18:00
👉 Смотрите программу и регистрируйтесь: https://sprts.cc/0ulpbs
Реклама. АО "Селектел". erid:2W5zFJSg6Ta
👍4