Требования для Kotlin библиотеки в 2024 году
С каждым годом требования к публичным библиотекам становятся все строже, появляется все больше либ, которые конкурируют между собой. Однако до сих пор на гитхабе есть множество библиотек, которые нарушают самые базовые правила их создания, не говоря уже про дополнительную заботу о пользователе.
Таким образом, если вы хотите сделать качественную Kotlin библиотеку, она должна соответствовать следующим требованиям:
🔹 Не нарушать обратную совместимость без строгой необходимости, как на уровне API, так и ABI
🔹 Быть задокументированной. Это касается как документации в коде, так и гайдов с примерами по ее использованию. Также хорошей практикой является выносить документацию на отдельный сайт с удобной навигацией и форматированием.
🔹 Иметь достаточное и качественное покрытие unit тестами
🔹 Не нарушать правила семантического версионирования
🔹 Иметь простой и понятный API
Все эти требования актуальны уже не первый год, но начиная с 2024 года, считаю нужно соблюдать еще одно важное правило:
❗️ Если ваша Kotlin библиотека может быть мультиплатформенной, она должна быть мультиплатформенной и поддерживать максимальное количество доступных таргетов в KMP. Если вы делаете библиотеку для Jetpack Compose, то она также должна поддерживать и Compose Multiplatform.
💡 Это очень важный шаг для реализации цели по запуску любого Android приложения на любой платформе.
А что думаете вы, готовы ли вы в своих библиотеках сделать поддержку KMP? Если нет, то почему?
С каждым годом требования к публичным библиотекам становятся все строже, появляется все больше либ, которые конкурируют между собой. Однако до сих пор на гитхабе есть множество библиотек, которые нарушают самые базовые правила их создания, не говоря уже про дополнительную заботу о пользователе.
Таким образом, если вы хотите сделать качественную Kotlin библиотеку, она должна соответствовать следующим требованиям:
Все эти требования актуальны уже не первый год, но начиная с 2024 года, считаю нужно соблюдать еще одно важное правило:
А что думаете вы, готовы ли вы в своих библиотеках сделать поддержку KMP? Если нет, то почему?
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Попалась интересная статья (EN, 7 мин) о том как перевести такой красивый интерфейс с Jetpack Compose на Compose Multiplatform и запустить его на iOS.
Помимо переноса кода в commonMain сорсет, переработки gradle скриптов, необходимо сделать следующее:
✅ Адаптировать ресурсы иконок, избавиться от ссылок на Android
✅ Изменить способ работы со шрифтами для iOS
✅ Убрать из общего кода все обращения к java классам, например к TimeUnit
✅ Не использовать native canvas
✅ Вынести реализацию BackHandler для разных сорсетов, поддержать обработку жестов в iOS
Исходный код примера можно посмотреть здесь
Помимо переноса кода в commonMain сорсет, переработки gradle скриптов, необходимо сделать следующее:
Исходный код примера можно посмотреть здесь
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Как пошарить версии библиотек между проектами
Думаю вы знаете про достаточно новую фичу Gradle под названием Version Catalog. С помощью этого каталога можно шарить одни и те же версии библиотек между модулями в проекте, причем обновление этих версий не инвалидирует весь кеш сборки, как это было ранее с выносом библиотек в buildSrc папку, поэтому на сегодняшний день использование Version Catalog является рекомендуемым подходом.
❓ Но как пошарить один и тот же каталог между разными проектами, которые находятся в разных репозиториях?
😐 Первое, что приходит на ум — это вынести единый .toml файл и подключать его через git submodule, но это не самое лучшее решение, так как уже недостаточно будет просто склонировать репозиторий проекта, и при этом придется внимательно следить за синхронизацией git модулей.
🙂 Гораздо лучше будет создать свой Gradle плагин, в котором будут описаны версии ваших библиотек, и затем нужно просто опубликовать и подключить его в другие проекты. Делается это гораздо проще, чем звучит! В статье (EN, 5 мин) подробно описано, как это сделать.
Но отсюда возникают другие проблемы:
1️⃣ Нельзя по клику перейти в .toml файл, как это было раньше
2️⃣ Новые версии библиотеки не будут подсвечиваться в студии
С первой проблемой особо ничего не поделать без написания IDEA плагина, а вот для проверки новых версий можно воспользоваться следующим плагином. Но обратите внимание, что обновления не будут автоматически проверяться у всех зависимостей, что указаны в каталоге версий, а только у тех, что подключены в gradle файле!
💬 А как вы шарите общие версии библиотек между проектами?
Думаю вы знаете про достаточно новую фичу Gradle под названием Version Catalog. С помощью этого каталога можно шарить одни и те же версии библиотек между модулями в проекте, причем обновление этих версий не инвалидирует весь кеш сборки, как это было ранее с выносом библиотек в buildSrc папку, поэтому на сегодняшний день использование Version Catalog является рекомендуемым подходом.
Но отсюда возникают другие проблемы:
С первой проблемой особо ничего не поделать без написания IDEA плагина, а вот для проверки новых версий можно воспользоваться следующим плагином. Но обратите внимание, что обновления не будут автоматически проверяться у всех зависимостей, что указаны в каталоге версий, а только у тех, что подключены в gradle файле!
Please open Telegram to view this post
VIEW IN TELEGRAM
Наткнулся на статью "38 ошибок в Compose" и возникло строгое ощущение, что статью писало ChatGPT, ибо ошибок и неточностей там огромное количество, даже начиная с самых первых пунктов.
1. Нам предлагают написать такой код заместо обычной лямбды:
При том, что rememberUpdatedState в целом используется для другого, в примере с обычной лямбдой было бы все окей, так как Compose умеет мемоизировать лямбды со стабильным типами.
В большинстве случаев вам не нужно ничего оптимизировать – это задача команды Compose. Но если все же нужно:
🔵 оберните лямбды с нестабильными типами в remember
🔵 передавайте часто меняющиеся параметры как Sate или лямбду
2. Далее нам предлагают заменить вложенные layout на Box или ConstraintLayout🤡
Тут даже комментировать не хочется, ибо в Compose есть правило одного прохода, вьюшки не меряются два раза, соответственно проблем с производительностью не будет.
Разумеется, это не все проблемы в статье, так что не верьте всему, что написано в интернете (мне тоже), а лучше читайте официальную документацию🗿
1. Нам предлагают написать такой код заместо обычной лямбды:
@Composable
fun MyComponent() {
var counter by remember { mutableStateOf(0) }
val clickAction = rememberUpdatedState { counter++ }
Button(onClick = { clickAction.value.invoke() }) {
Text("Clicked $counter times")
}
}
При том, что rememberUpdatedState в целом используется для другого, в примере с обычной лямбдой было бы все окей, так как Compose умеет мемоизировать лямбды со стабильным типами.
В большинстве случаев вам не нужно ничего оптимизировать – это задача команды Compose. Но если все же нужно:
2. Далее нам предлагают заменить вложенные layout на Box или ConstraintLayout
Тут даже комментировать не хочется, ибо в Compose есть правило одного прохода, вьюшки не меряются два раза, соответственно проблем с производительностью не будет.
Разумеется, это не все проблемы в статье, так что не верьте всему, что написано в интернете (мне тоже), а лучше читайте официальную документацию
Please open Telegram to view this post
VIEW IN TELEGRAM
В этом году я стал одним из членов программного комитета на конференции Podlodka Android Crew.
Мы сейчас готовим 11 сезон и у нас уже есть три крутых потенциальных темы сезона:
🎨 Оптимизация UI
📈 Карьера разработчика
⚙️ Инструменты Android разработчика
И нам нужна ваша помощь в выборе лучшей темы, которую бы вы точно хотели послушать. Прошу вас поучаствовать в опросе, это не займет много времени. К тому же будет разыгрываться бесплатная проходка на конференцию между всеми, кто заполнил анкету.
⚙️ Если у вас есть вопросы по конференции, то смело пишите в комментарии
Мы сейчас готовим 11 сезон и у нас уже есть три крутых потенциальных темы сезона:
И нам нужна ваша помощь в выборе лучшей темы, которую бы вы точно хотели послушать. Прошу вас поучаствовать в опросе, это не займет много времени. К тому же будет разыгрываться бесплатная проходка на конференцию между всеми, кто заполнил анкету.
Please open Telegram to view this post
VIEW IN TELEGRAM
Коллега из сообщества (Максим Казанцев) опубликовал в публичный доступ 6 видео из своего курса по Kotlin Multiplatform.
🔸 О курсе и знакомство с автором
🔸 Инициализация проекта на KMP
🔸 Задачи в Gradle
🔸 Подключение Desktop + Compose
🔸 Добавление Android модуля
🔸 Подключение iOS таргета
Курс рассчитан на разработчиков от Junior+ и выше. Поэтому если вы не работали с KMP, или создавали проект с помощью визарда, но не совсем понимали как это сделать самостоятельно, то этот курс определенно для вас!
Приятного просмотра🤔
Курс рассчитан на разработчиков от Junior+ и выше. Поэтому если вы не работали с KMP, или создавали проект с помощью визарда, но не совсем понимали как это сделать самостоятельно, то этот курс определенно для вас!
Приятного просмотра
Please open Telegram to view this post
VIEW IN TELEGRAM
Давно на этом канале не было постов, но я пришел к вам с двумя хорошими новостями:
1️⃣ Я за это время сделал один интересный доклад про привычки Android разработки, которые мешают адаптировать приложение под KMP и скоро опубликуем его в открытый доступ, так что stay tuned
2️⃣ А также мы с командой подготовили новый 11 сезон Podlodka Android Crew с темой "Оптимизация UI".
Мы старались найти классных спикеров, помочь им с подготовкой и сезон получился довольно насыщенный:
🔹 Послушаем как продавать производительность бизнесу
🔹 Узнаем как работать с такими инструментами как Perfetto, JankStats и Jetpack Macrobenchmark
🔹 Увидим на примере как оптимизировать приложение на Jetpack Compose
🔹 А также поболеем за участников баттла и сами поучаствуем в квизе по производительности UI.
Конференция стартует уже 25 марта, так что присоединяйтесь, будет круто, все подробности на сайте.
🎁 Ну и куда же без розыгрыша? Давайте разыграем одну проходку на Android Crew, единственное условие – быть подписанными на этот telegram канал @kotlin_adept.
Для участия в розыгрыше достаточно нажать на кнопку «Принять участие» под следующим постом и мы определим победителя рандомно уже в это воскресенье, удачи🤝
Мы старались найти классных спикеров, помочь им с подготовкой и сезон получился довольно насыщенный:
Конференция стартует уже 25 марта, так что присоединяйтесь, будет круто, все подробности на сайте.
Для участия в розыгрыше достаточно нажать на кнопку «Принять участие» под следующим постом и мы определим победителя рандомно уже в это воскресенье, удачи
Please open Telegram to view this post
VIEW IN TELEGRAM
Розыгрыш проходки на 11 сезон конференции Podlodka Android Crew
Kotlin Adept Notes
Розыгрыш проходки на 11 сезон конференции Podlodka Android Crew
Выбор дополнительных победителей (в количестве 1):
Победитель:
1. Mikhail (@zykloned)
Проверить результаты
Победитель:
1. Mikhail (@zykloned)
Проверить результаты
Кастомные маски для TextField в Compose
Раньше в Android View реализовать маску для номера телефона, не говоря уже про что-то кастомное было далеко не самой простой задачей и люди, чтобы облегчить себе жизнь, использовали сторонние библиотеки, такие как Decoro.
Но теперь с приходом Compose надобность в сторонних решениях практически отпала, ведь реализовать кастомную маску для TextField можно буквально в 40 строк кода😱 , и это возможно благодаря продуманному и простому API интерфейса
Фишка в том, что
🔸 Определить как исходный текст будет трансформироваться в текст с маской
🔸 Предоставить двухсторонний маппинг для правильного смещения курсора в поле ввода
📘 Подробнее можно почтитать в статье, где разобран случай маски для ввода даты и с полностью кастомизируемой маской
#Compose
Раньше в Android View реализовать маску для номера телефона, не говоря уже про что-то кастомное было далеко не самой простой задачей и люди, чтобы облегчить себе жизнь, использовали сторонние библиотеки, такие как Decoro.
Но теперь с приходом Compose надобность в сторонних решениях практически отпала, ведь реализовать кастомную маску для TextField можно буквально в 40 строк кода
VisualTransformation
.Фишка в том, что
VisualTransformation
, как бы это неожиданно не звучало, влияет всего лишь на визуальное отображение, а не реальное значение поля, и, чтобы реализовать любую маску, достаточно сделать две вещи:
var out = ""
text.text.forEachIndexed { index, char ->
when (index) {
2 -> out += "/$char"
4 -> out += "/$char"
else -> out += char
}
}
val numberOffsetTranslator = object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
if (offset <= 2) return offset
if (offset <= 4) return offset + 1
return offset + 2
}
override fun transformedToOriginal(offset: Int): Int {
if (offset <= 2) return offset
if (offset <= 5) return offset - 1
return offset - 2
}
}
#Compose
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
Media is too big
VIEW IN TELEGRAM
Немультиплатформенные привычки Android-разработки
Алексей Панов делится тем, как Android разработчику начать писать на Kotlin Multiplatform и отучиться от платформенных привычек
2:46 KMP Стек технологий
11:32 Переход с Java API
18:01 Переход с Android API
29:03 Использование Compose
36:07 Итоговые советы
Смотрите разбор на разных площадках:
👉YouTube
👉VK Video
👉Дзен
#AndroidBroadcast #кодинг
Алексей Панов делится тем, как Android разработчику начать писать на Kotlin Multiplatform и отучиться от платформенных привычек
2:46 KMP Стек технологий
11:32 Переход с Java API
18:01 Переход с Android API
29:03 Использование Compose
36:07 Итоговые советы
Смотрите разбор на разных площадках:
👉YouTube
👉VK Video
👉Дзен
#AndroidBroadcast #кодинг
ViewModel в KMP
Еще не так давно считалось, что ViewModel — это только Android only история и использовать ее в общем коде в мультиплатформе не получится, но в мире KMP все меняется очень быстро:
😀 Google переписали ViewModel на Kotlin и адаптировали ее lifecycle под мультиплатформу
😀 JetBrains сделали ее полностью мультиплатформенной, заодно адаптировав и компоузовскую навигацию
Из нюансов, нужно явно создавать инстанс ViewModel, даже с пустым конструктором! Но при этом сохранилась поддержка savedStateHandle.
Эти изменения безусловно положительно повлияют на популяризацию KMP, такими темпами скоро достаточно будет просто перенести весь код Android приложения в папку commonMain, адаптировать gradle скрипты и можно запускать приложение на любой платформе. Звучит круто, не правда ли!👌
Но все же я не рекомендую продолжать использовать ViewModel напрямую, а думать о ней как о контейнере! Например, так реализован InstanceKeeper в Essenty.
Это дает несколько плюсов:
😀 Вы можете сами управлять ЖЦ вашего компонента с логикой, делать его как синглтон, инжектить друг в друга, а не привязывать его только к ЖЦ ViewModel
😀 Вы облегчаете внедрение зависимостей, так как по сути вы создаете обычный класс
Если все равно непонятно о чем речь, то советую прочитать эту статью, где подробно рассмотрена эта концепция.
А что вы думаете об использовании ViewModel в KMP❓
Еще не так давно считалось, что ViewModel — это только Android only история и использовать ее в общем коде в мультиплатформе не получится, но в мире KMP все меняется очень быстро:
Из нюансов, нужно явно создавать инстанс ViewModel, даже с пустым конструктором! Но при этом сохранилась поддержка savedStateHandle.
@Composable
fun MyScreen(viewModel: MyViewModel = viewModel { MyViewModel(createSavedStateHandle()) }) {
...
}
Эти изменения безусловно положительно повлияют на популяризацию KMP, такими темпами скоро достаточно будет просто перенести весь код Android приложения в папку commonMain, адаптировать gradle скрипты и можно запускать приложение на любой платформе. Звучит круто, не правда ли!
Но все же я не рекомендую продолжать использовать ViewModel напрямую, а думать о ней как о контейнере! Например, так реализован InstanceKeeper в Essenty.
Это дает несколько плюсов:
Если все равно непонятно о чем речь, то советую прочитать эту статью, где подробно рассмотрена эта концепция.
А что вы думаете об использовании ViewModel в KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
Сегодня буду выступать на митапе от Usetech. Буду рассказывать обновленную версию своего доклада, ведь с тех пор картина сильно поменялась, теперь Room, ViewModel, Jetpack Navigation Compose уже можно использовать в KMP. Так что грань между Android и мультиплатформенной разработкой все больше стирается.
Поэтому если не смотрели доклад или хотите узнать, что поменялось и задать вопросы, то приходите сегодня в 15:00 мск на прямую трансляцию.
Также, помимо меня, на митапе выступят Анна Жаркова с докладом про SwiftUI и Евгений Сатуров с докладом про Flutter.
Регистрируйтесь по ссылке и до встречи🤝
Поэтому если не смотрели доклад или хотите узнать, что поменялось и задать вопросы, то приходите сегодня в 15:00 мск на прямую трансляцию.
Также, помимо меня, на митапе выступят Анна Жаркова с докладом про SwiftUI и Евгений Сатуров с докладом про Flutter.
Регистрируйтесь по ссылке и до встречи
Please open Telegram to view this post
VIEW IN TELEGRAM
В докладе много всего интересного про подкапотную магию работы Compose, а именно:
Приятного просмотра
Please open Telegram to view this post
VIEW IN TELEGRAM
Также Mobius опубликовали наш совместный с Дмитрием Григорьевым квиз по Compose🎨
Квиз состоит из 4 блоков:
🟡 Разминочные вопросы
🔵 Вопросы по модификаторам
🟠 Вопросы по рекомпозиции
🔵 Хардкорные вопросы про подкапотную магию Compose
Так что, если не смотрели, то проверьте свои знания по Compose и напишите в комментариях на сколько вопросов удалось ответить правильно и какой вопрос показался самым сложным🤔
Квиз состоит из 4 блоков:
Так что, если не смотрели, то проверьте свои знания по Compose и напишите в комментариях на сколько вопросов удалось ответить правильно и какой вопрос показался самым сложным
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Коллега из Контура, Евгений Мельцайкин, написал статью о том, как сделать такую кнопку с помощью кастомного Layout в Compose и как оптимизировать ее, чтобы достичь минимального количества рекомпозиций. Приятного чтения 📕
Исходный код можно посмотреть здесь🐱
А вы сможете на взгляд определить какая кнопка сделана оптимально по количеству рекомпозиций?
#Compose
Исходный код можно посмотреть здесь
А вы сможете на взгляд определить какая кнопка сделана оптимально по количеству рекомпозиций?
#Compose
Please open Telegram to view this post
VIEW IN TELEGRAM
Обзор Mobius 2024 Spring
Прошла очередная конференция Mobius и в этот раз я даже посмотрел больше двух докладов, так как фармить мерч удаленно не получается😒
И в целом сезон получился довольно интересным с хорошими и полезными докладами.
Вот мой личный топ:
🔸 Тестирование дизайн-системы. Тут автор рассказывает про то, как они работают со snapshot тестами, с какими проблемами столкнулись, какие уроки из этого вынесли и как у них получилось избавиться от эмулятора при прогоне тестов.
Для нас сейчас это довольно актуальная тема, у нас уже был первый подход к скриншот тестированию, но мы также наткнулись на проблемы и нам ещё предстоит их преодолеть.
🔸 Единая авторизация Ozon ID. Довольно лёгкий и менее технический доклад про способы авторизации, про часть из которых я узнал из доклада и выглядят они действительно интересно.
🔵 Бессмертное приложение. Скорее не доклад, а больше справочник по разным лайфхакам как продлить время жизни приложения в фоне и пережить force stop, которые вы вряд ли найдете на StackOverflow.
🔹 Как избавиться от рекурсии. Хардкорный, но интересный доклад про различные способы оптимизации рекурсии.
Так что, советую посмотреть эти доклады в записи, но если у вас нет билета на Mobius, то пишите в комментарии какую тему хотелось бы осветить и я напишу пост про самые важные инсайты из докладов💻
Прошла очередная конференция Mobius и в этот раз я даже посмотрел больше двух докладов, так как фармить мерч удаленно не получается
И в целом сезон получился довольно интересным с хорошими и полезными докладами.
Вот мой личный топ:
Для нас сейчас это довольно актуальная тема, у нас уже был первый подход к скриншот тестированию, но мы также наткнулись на проблемы и нам ещё предстоит их преодолеть.
Так что, советую посмотреть эти доклады в записи, но если у вас нет билета на Mobius, то пишите в комментарии какую тему хотелось бы осветить и я напишу пост про самые важные инсайты из докладов
Please open Telegram to view this post
VIEW IN TELEGRAM
Скриншот-тестирование
Практика скриншот-тестирования в Android началась еще более 10 лет назад и актуальна по сей день, за это время появилось огромное количество разных библиотек (Paparazzi, Shot, Testify и другие), но у всех библиотек есть существенный недостаток — поддержка. Всегда есть риски, что библиотеку перестанут поддерживать или будут обновлять зависимости несвоевременно.
И ребята из Тинькофф для тестирования дизайн-системы пошли другим путем, не используя сторонние библиотеки, так как все, что нужно для скриншот-тестирования уже есть в Android! (на самом деле нет)
Достаточно взять эталонный и текущий скриншот, сконвертировать все в Bitmap и попарно сравнить пиксели:
Но разумеется это только верхушка айсберга и, чтобы построить хороший процесс тестирования дизайн-системы, нужно решить еще множество проблем.
И вот список рекомендаций из их доклада про что нужно помнить:
▫️ Подготовьте storybook и используете эти же состояния компонентов для тестирования
▫️ Сделайте удобный тулинг для обновления эталонных скриншотов и просмотра диффа скриншотов
▫️ Используйте CI как единый источник правды для создания эталонных скриншотов, так как на разных процессорах графика может отличаться
▫️ Избавляйтесь от запуска тестов на эмуляторе, в этом может Robolectric с режимом
▫️ Подумайте о генерации тестов через KSP
Но, что если ваш проект полностью написан на Jetpack Compose? Неужели нет других вариантов скриншот-тестирования? Об этом расскажу в следующем посте, так что stay tuned!
#Testing #SnapshotTesting #Android
Практика скриншот-тестирования в Android началась еще более 10 лет назад и актуальна по сей день, за это время появилось огромное количество разных библиотек (Paparazzi, Shot, Testify и другие), но у всех библиотек есть существенный недостаток — поддержка. Всегда есть риски, что библиотеку перестанут поддерживать или будут обновлять зависимости несвоевременно.
И ребята из Тинькофф для тестирования дизайн-системы пошли другим путем, не используя сторонние библиотеки, так как все, что нужно для скриншот-тестирования уже есть в Android! (на самом деле нет)
Достаточно взять эталонный и текущий скриншот, сконвертировать все в Bitmap и попарно сравнить пиксели:
val referenceBitmap = BitmapFactory.decodeFile("assets/1.jpg")
val actualBitmap = onView(withId(R.id.mainContent)).captureToBitmap()
val isSameImage = compareBitmaps(referenceBitmap, actualBitmap)
assertTrue(isSameImage)
Но разумеется это только верхушка айсберга и, чтобы построить хороший процесс тестирования дизайн-системы, нужно решить еще множество проблем.
И вот список рекомендаций из их доклада про что нужно помнить:
@GraphicsMode(NATIVE)
Но, что если ваш проект полностью написан на Jetpack Compose? Неужели нет других вариантов скриншот-тестирования? Об этом расскажу в следующем посте, так что stay tuned!
#Testing #SnapshotTesting #Android
Please open Telegram to view this post
VIEW IN TELEGRAM