Kotlin Adept Notes – Telegram
Kotlin Adept Notes
2.35K subscribers
81 photos
9 videos
133 links
Канал о разработке на Kotlin и обо всем, что с ним связано
По всем вопросам и рекламе: @ajiekcx
Download Telegram
Проблема версионирования

Продолжаем тему 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
👍282
🟥 Сегодня провожу публичное собеседование по Kotlin Multiplatform на YouTube-канале Android Broadcast в 19:00 мск.

Это уже мое четвертое публичное собеседование, в котором я стараюсь раскрыть основные аспекты работы с современными технологиями:

⏸️ Собеседование по Kotlin Coroutines
⚙️ Собеседование по Jetpack Compose
🤖 Собеседование мобильного разработчика

Сегодня на собеседовании будет задачка на ревью проекта с плохим кодом, но с упором на KMP. И по ходу эфира обсудим все нюансы интеграции общего кода с iOS.

Если вам интересна эта тема, обязательно приходите на прямой эфир, будет интересно! А в конце я смогу ответить на все ваши вопросы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥483🤡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
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
Please open Telegram to view this post
VIEW IN TELEGRAM
25👍12❤‍🔥3
10 кругов ада, или как вручную перенести все фотки из-за аккаунта разработчика

Так вышло, что фотографирую я не очень часто, и только сейчас у меня закончилось место на Google Диске. Теперь в каждом своём приложении Google показывает страшные баннеры и вынуждает купить подписку 🤑

Что ж, убедили, идём покупать. Но с русским платёжным профилем ничего не купить. Зачем тогда предлагали? Ну да ладно.

Пытаемся поменять платёжный профиль, но этого сделать нельзя из-за активного аккаунта разработчика 🤨

Аккаунт я давно забросил и все приложения там удалил, но Google заодно «удалил» и мой аккаунт, так как я не подтвердил личность.

Пишу в техподдержку, чтобы аккаунт удалили окончательно и я смог поменять платёжный профиль. На что получаю ответ: сделать это нельзя, если на аккаунте нет активных приложений 😵

Тут я понял, что ситуация патовая и надо что-то делать. Одним из вариантов было создать новый аккаунт для фоток и заодно перенести все фото на Яндекс Диск.

Окей, качаем через Google Takeout архив со всеми фотками. Метаданные EXIF лежат там в отдельном JSON-файле, соответственно, ни данных о дате, ни геолокации в фотке нет, и нужно это как-то восстанавливать.

Я нашёл скрипт на Python, который это делает, и пришлось ещё немного подвайбкодить, чтобы всё заработало...

Вот такой вот квест получился. А если бы аккаунта разработчика не было, все бы решилось проще, так что думайте 😏

#Offtop
Please open Telegram to view this post
VIEW IN TELEGRAM
1🤯22😁83👍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
👍12😐7
Как улучшить дальность сканирования кодов маркировки

Библиотеки вроде Google ML Kit, ZXing или его аналога на C++ со стандартными настройками камеры имеют довольно посредственную дальность сканирования, приходится подносить камеру очень близко, чтобы хоть что-то отсканировать. Особенно это касается акцизных марок нового образца. При этом, если взглянуть на коммерческие решения, они работают на голову выше.

Как можно улучшить ситуацию?

🟢Как ни странно, можно попробовать уменьшить разрешение камеры, двух мегапикселей более чем достаточно для распознавания.
🟢Увеличить параметр zoomRatio в камере по-умолчанию, например, установить 1.5f вместо 1f.
🟢Реализовать автоматический зум к потенциальным кодам. Для этого в ML Kit появились настройки enableAllPotentialBarcodes и ZoomSuggestionOptions.
🟢Ограничить размер зоны сканирования.

Наверняка можно придумать что-то ещё. Хотелось бы спросить совета у тех, кто уже сталкивался с подобной задачей, есть идеи, что еще можно сделать?

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:


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-летним опытом.

Узнайте все детали курса на сайте 🔗
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
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
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍98🔥147🤯4
QA Mobile MeetUp
Если вы тестируете мобильные приложения, приходите на митап Спортса” и Selectel.

Обсудим насущное: сбор ферм девайсов, генерацию тестовых данных, ревью тест-кейсов и тестирование рекламы.
📍оффлайн в Москве и онлайн
🗓5 декабря, 18:00

👉 Смотрите программу и регистрируйтесь: https://sprts.cc/0ulpbs

Реклама. АО "Селектел". erid:2W5zFJSg6Ta
👍4