Kotlin Adept Notes

Description
Канал о разработке на Kotlin и обо всем, что с ним связано
Автор: @ajiekcx
Advertising
We recommend to visit

Официальный новостной канал криптобиржи OKX | www.okx.com на русском языке.

💬 Комьюнити: t.me/okx_russian

👨‍💻 Поддержка: [email protected]

АДМИН: @DaniiOKX
Маркетинг: @CoffeeTrends

Last updated 4 days, 8 hours ago

Здесь простым языком про TON, DFC и крипту.

Принимаем автоматически.
Ссылка для друзей: https://t.me/+-EOfWx2pRKhmNGE6
Связь: @deftalk_bot

Last updated 1 month ago

#1 канал о блокчейне, криптовалютах и децентрализованных финансах.

🔥 Реклама — @DCTeam

Last updated 8 hours ago

3 months, 2 weeks ago

Бессмертное приложение

Продолжим разбирать доклады с предыдущего Mobius. И сегодня поговорим о том, как пережить force stop и запустить приложение после его установки из стора без действий пользователя.

Мы знаем, что если пользователь принудительно остановит в настройках приложение, то без повторного его открытия все фоновые операции будут недоступны, в том числе и пуши. Но эту проблему можно частично решить, для этого нам понадобится ContactsProvider и Account Synchronization.

  1. Регистрируем в манифесте provider с метадатой ContactDirectory. Тогда при открытии приложения "Контакты" ContactsProvider опросит всех, у кого есть эта метадата, соответственно поднимется наш провайдер и вызовется метод onCreate у Application даже без первичного запуска приложения.

```

android:name="android.content.ContactDirectory"
android:value="true" />

```

  1. Далее мы можем зарегистрировать свой SyncAdaper для синхронизации аккаунтов, он может не иметь никакой логики, главное включить автоматический и периодичный синк. Тогда система сможет при синхронизации аккаунтов сама пробудить процесс даже после force stop!

Но согласитесь, это же не бессмертие, а больше похоже на некромантию? Убиваем и воскрешаем процесс через какое-то время ?

Однако есть способ по-настоящему пережить force stop, правда работает он не гарантировано и ни в каких продакшн приложениях лучше его не использовать ⚠️

Суть в том, что у системы есть 40 попыток, чтобы убить процесс с периодичностью 5мс, и если мы будем за это время создавать новые процессы, то система в теории просто сдастся. То есть процессы будут поднимать друг друга пока не пройдет достаточно времени, чтобы система оставила их в покое. Посмотреть на это безумие можно в репозитории.

Всем разработчикам долгоживущих приложений, а пользователям соболезнования по поводу батарейки в их смартфонах ?

#Android #UnderTheHood

3 months, 3 weeks ago

Скриншот-тестирование в Compose

Google не так давно выкатили свой тулинг для скриншот-тестирования в Compose в экспериментальном режиме и работает он на основе Compose Preview ?

У меня довольно скпептическое отношение к превью, за все время работы с Compose у меня постоянно были какие-то проблемы с этим механизмом, а с приходом Compose Multiplatform заставить превьюшки работать тот ещё челлендж, более менее дела с превью обстоят только в новой IDE Fleet, но там ещё ворох других проблем.

Так вот, вернёмся к тестированию, я попробовал этот способ и что могу сказать по текущему состоянию тулинга:

?Официальное решение для скриншот-тестирования
?Генерация отчёта с диффом изображений
?Уже относительно работает и можно использовать на свой страх и риск
?Тесты прогоняются без эмулятора и соответственно прогоняются быстро

?Названия сгенерированных скриншотов нельзя поменять
?Нельзя выборочно обновить эталонный скриншот
?Нужно использовать специальные gradle таски для валидации скриншотов, потребуются доработки на CI
?Нельзя настроить минимальный порог отличий между скриншотами
?Только для Android

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

#Compose #SnapshotTesting

5 months, 1 week ago

ViewModel в KMP

Еще не так давно считалось, что ViewModel — это только Android only история и использовать ее в общем коде в мультиплатформе не получится, но в мире KMP все меняется очень быстро:
?Google переписали ViewModel на Kotlin и адаптировали ее lifecycle под мультиплатформу
?JetBrains сделали ее полностью мультиплатформенной, заодно адаптировав и компоузовскую навигацию

Из нюансов, нужно явно создавать инстанс ViewModel, даже с пустым конструктором! Но при этом сохранилась поддержка savedStateHandle.

```

@Composable
fun MyScreen(viewModel: MyViewModel = viewModel { MyViewModel(createSavedStateHandle()) }) {
...
}

```

Эти изменения безусловно положительно повлияют на популяризацию KMP, такими темпами скоро достаточно будет просто перенести весь код Android приложения в папку commonMain, адаптировать gradle скрипты и можно запускать приложение на любой платформе. Звучит круто, не правда ли! ?

Но все же я не рекомендую продолжать использовать ViewModel напрямую, а думать о ней как о контейнере! Например, так реализован InstanceKeeper в Essenty.

Это дает несколько плюсов:
?Вы можете сами управлять ЖЦ вашего компонента с логикой, делать его как синглтон, инжектить друг в друга, а не привязывать его только к ЖЦ ViewModel
?Вы облегчаете внедрение зависимостей, так как по сути вы создаете обычный класс

Если все равно непонятно о чем речь, то советую прочитать эту статью, где подробно рассмотрена эта концепция.

А что вы думаете об использовании ViewModel в KMP

6 months, 1 week ago

Кастомные маски для TextField в Compose

Раньше в Android View реализовать маску для номера телефона, не говоря уже про что-то кастомное было далеко не самой простой задачей и люди, чтобы облегчить себе жизнь, использовали сторонние библиотеки, такие как Decoro.

Но теперь с приходом Compose надобность в сторонних решениях практически отпала, ведь реализовать кастомную маску для TextField можно буквально в 40 строк кода ?, и это возможно благодаря продуманному и простому API интерфейса 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

6 months, 2 weeks ago

Розыгрыш проходки на 11 сезон конференции Podlodka Android Crew

8 months ago

В этом году я стал одним из членов программного комитета на конференции Podlodka Android Crew.

Мы сейчас готовим 11 сезон и у нас уже есть три крутых потенциальных темы сезона:
? Оптимизация UI
? Карьера разработчика
⚙️ Инструменты Android разработчика

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

⚙️Если у вас есть вопросы по конференции, то смело пишите в комментарии

8 months ago

Наткнулся на статью "38 ошибок в Compose" и возникло строгое ощущение, что статью писало ChatGPT, ибо ошибок и неточностей там огромное количество, даже начиная с самых первых пунктов.

  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. Но если все же нужно:
?оберните лямбды с нестабильными типами в remember
?передавайте часто меняющиеся параметры как Sate или лямбду

  1. Далее нам предлагают заменить вложенные layout на Box или ConstraintLayout ?

Тут даже комментировать не хочется, ибо в Compose есть правило одного прохода, вьюшки не меряются два раза, соответственно проблем с производительностью не будет.

Разумеется, это не все проблемы в статье, так что не верьте всему, что написано в интернете (мне тоже), а лучше читайте официальную документацию?

8 months, 1 week ago

Как пошарить версии библиотек между проектами

Думаю вы знаете про достаточно новую фичу Gradle под названием Version Catalog. С помощью этого каталога можно шарить одни и те же версии библиотек между модулями в проекте, причем обновление этих версий не инвалидирует весь кеш сборки, как это было ранее с выносом библиотек в buildSrc папку, поэтому на сегодняшний день использование Version Catalog является рекомендуемым подходом.

Но как пошарить один и тот же каталог между разными проектами, которые находятся в разных репозиториях?

? Первое, что приходит на ум — это вынести единый .toml файл и подключать его через git submodule, но это не самое лучшее решение, так как уже недостаточно будет просто склонировать репозиторий проекта, и при этом придется внимательно следить за синхронизацией git модулей.

? Гораздо лучше будет создать свой Gradle плагин, в котором будут описаны версии ваших библиотек, и затем нужно просто опубликовать и подключить его в другие проекты. Делается это гораздо проще, чем звучит! В статье (EN, 5 мин) подробно описано, как это сделать.

Но отсюда возникают другие проблемы:
1️⃣Нельзя по клику перейти в .toml файл, как это было раньше
2️⃣Новые версии библиотеки не будут подсвечиваться в студии

С первой проблемой особо ничего не поделать без написания IDEA плагина, а вот для проверки новых версий можно воспользоваться следующим плагином. Но обратите внимание, что обновления не будут автоматически проверяться у всех зависимостей, что указаны в каталоге версий, а только у тех, что подключены в gradle файле!

?А как вы шарите общие версии библиотек между проектами?

9 months, 2 weeks ago

Требования для Kotlin библиотеки в 2024 году

С каждым годом требования к публичным библиотекам становятся все строже, появляется все больше либ, которые конкурируют между собой. Однако до сих пор на гитхабе есть множество библиотек, которые нарушают самые базовые правила их создания, не говоря уже про дополнительную заботу о пользователе.

Таким образом, если вы хотите сделать качественную Kotlin библиотеку, она должна соответствовать следующим требованиям:

?Не нарушать обратную совместимость без строгой необходимости, как на уровне API, так и ABI
?Быть задокументированной. Это касается как документации в коде, так и гайдов с примерами по ее использованию. Также хорошей практикой является выносить документацию на отдельный сайт с удобной навигацией и форматированием.
?Иметь достаточное и качественное покрытие unit тестами
?Не нарушать правила семантического версионирования
?Иметь простой и понятный API

Все эти требования актуальны уже не первый год, но начиная с 2024 года, считаю нужно соблюдать еще одно важное правило:

❗️Если ваша Kotlin библиотека может быть мультиплатформенной, она должна быть мультиплатформенной и поддерживать максимальное количество доступных таргетов в KMP. Если вы делаете библиотеку для Jetpack Compose, то она также должна поддерживать и Compose Multiplatform.

? Это очень важный шаг для реализации цели по запуску любого Android приложения на любой платформе.

А что думаете вы, готовы ли вы в своих библиотеках сделать поддержку KMP? Если нет, то почему?

We recommend to visit

Официальный новостной канал криптобиржи OKX | www.okx.com на русском языке.

💬 Комьюнити: t.me/okx_russian

👨‍💻 Поддержка: [email protected]

АДМИН: @DaniiOKX
Маркетинг: @CoffeeTrends

Last updated 4 days, 8 hours ago

Здесь простым языком про TON, DFC и крипту.

Принимаем автоматически.
Ссылка для друзей: https://t.me/+-EOfWx2pRKhmNGE6
Связь: @deftalk_bot

Last updated 1 month ago

#1 канал о блокчейне, криптовалютах и децентрализованных финансах.

🔥 Реклама — @DCTeam

Last updated 8 hours ago