Часы. Часы? Часы!
Рекомендации по использованию сторонних фреймворков от разработчицы из Гугла. Даже если не занимаетесь поддержкой wearable девайсов, то интересно глянуть на особенности разработки. Google I/O показал много обновлений для часов!
👉 Сборник Horologist библиотек. Помогают следовать гайдлайнам гугла. Например скорлу или удостовериться что часть элементов не скрыто под скруглением часов
👉 Скриншоты для странички Google Play, чтоб заявить о поддержке часов, даже если нет идеального девайса
👉 Шрифты и Splash screen (Wow!)
👉 Основная дока
Рекомендации по использованию сторонних фреймворков от разработчицы из Гугла. Даже если не занимаетесь поддержкой wearable девайсов, то интересно глянуть на особенности разработки. Google I/O показал много обновлений для часов!
👉 Сборник Horologist библиотек. Помогают следовать гайдлайнам гугла. Например скорлу или удостовериться что часть элементов не скрыто под скруглением часов
👉 Скриншоты для странички Google Play, чтоб заявить о поддержке часов, даже если нет идеального девайса
👉 Шрифты и Splash screen (Wow!)
👉 Основная дока
Medium
Tools and libraries to help your Wear OS app satisfy Google Play app quality requirements
Learn about available tools and libraries to help you easily meet Wear OS app quality requirements to be published on the Google Play…
Кэширование в Android
Автор рассматривает и предлагает архитектурные решения для следующих типов кэширования:
👉 Cache Only
👉 Network Only
👉 Network First
👉 Cache First - Network Second
👉 Cache First - Network for Later
👉 Cache First - Network Once
✍️ Бонусом, кэширование через networkBoundResource
Выглядит больше как шпаргалка по проектированию кэширования приложения на этапе интервью, но схемы однозначно стоит посмотреть и, возможно, забрать к себе в команду
Автор рассматривает и предлагает архитектурные решения для следующих типов кэширования:
👉 Cache Only
👉 Network Only
👉 Network First
👉 Cache First - Network Second
👉 Cache First - Network for Later
👉 Cache First - Network Once
Выглядит больше как шпаргалка по проектированию кэширования приложения на этапе интервью, но схемы однозначно стоит посмотреть и, возможно, забрать к себе в команду
Please open Telegram to view this post
VIEW IN TELEGRAM
О создании Preview в Jetpack Compose
Как вы подкладываете и обновляете данные для
👉 Хардкодить данные напрямую
👉 Класть все данные в обьект и подменять в процессе подстановки. А более аккуратный способ — это воспользоваться
👉 Написать полноценный отдельный фабричный метод для описания состояния
👉 Использование существующего state holder
У нас в команде решили для каждого UI-класса определять несколько
Как вы подкладываете и обновляете данные для
@Preview
? В статье предлагается:👉 Хардкодить данные напрямую
👉 Класть все данные в обьект и подменять в процессе подстановки. А более аккуратный способ — это воспользоваться
PreviewParameterProvider
(Хорошо описано тут)👉 Написать полноценный отдельный фабричный метод для описания состояния
@Preview
. Мне кажется что это оверинжениринг, только если вы не всецело полагаетесь на превью в работе👉 Использование существующего state holder
У нас в команде решили для каждого UI-класса определять несколько
mock()
функций с основными кейсами. В итоге у нас есть базовые превью, а при переиспользовании всегда видны возможные коллизии на основных кейсах.Dladukedev
The Many Approaches to Providing @Preview data in Jetpack Compose
Jetpack Compose Previews make for faster development and prototyping but the problem of providing data to the component has many solutions. Here is a review of those different solutions, how they might be applied in a given project, and the pros and cons…
System UI Compatibility and Immersive Status Bar
Разбираемся как в Compose обращаться с областью взаимодействия приложения
👉
👉
👉
Разбираемся как в Compose обращаться с областью взаимодействия приложения
👉
enableEdgeToEdge()
- растянуть область и забрать контроль у системы👉
WindowInsets
понять область отступа системных компонентов и вставить в padding
вашего объекта👉
Modifier.systemBarsPadding()
или Modifier.safeDrawingPadding()
сделать тоже самое, но с помощью модификатораПосмотрите на этот кусочек кода. Выглядит странно, хотя точно используется вашим приложением. Ну а кто транзитивно не использует okio?
Именно с этого момента начинается статья об оптимизации подсчета количества символов в числе. Итоговые результаты такие:
Именно с этого момента начинается статья об оптимизации подсчета количества символов в числе. Итоговые результаты такие:
Немного анонсов грядущих изменений в Kotlin. Вероятно, появится объединение типов и ошибок
Более подробно в тикете: kotl.in/f28fo8
Источник
Это не финальный вид, а только предположение о том, как может выглядеть реализация
Более подробно в тикете: kotl.in/f28fo8
Источник
Это не финальный вид, а только предположение о том, как может выглядеть реализация
Android Good Reads
Неплохая первоапрельская шутка про котлин. Журнальчик https://kotlintoday.com/ Это мы читаем 😁
Первоапрельская шутка зашла на ура и теперь это полноценный журнал!
Сравниваем 2 APK на уровне dex. Не маст-хев инструмент, но посмотреть на сколько хорошо работают ваши proguard правила и сверить apk от релиза к релизу может быть удобно.
Сам инструмент: https://github.com/theapache64/dex-diff
Сам инструмент: https://github.com/theapache64/dex-diff
Про новые layout с Google I/O
Новые
👉 Ключевое изменение в возможности получать
👉 Вы могли заметить, что теперь можно указать максимальное количество элементов, а это значит что в элемент можно накинуть на 1 больше элемент чем мы разрешили. Что произойдет? Сработает 1 из 4 overflow policy:
Новые
ContextualFlowRow
и ContextualFlowColumn
дают чуть больше контроля над элементами, по сравнению со стандартными FlowRow
и FlowColumn
, хотя они тоже получили небольшое обновление
val items = List(100) { Random.nextFloat() }
ContextualFlowRow(
itemCount = items.size,
maxLines = 3,
maxItemsInEachRow = Int.MAX_VALUE,
horizontalArrangement = Arrangement.Start,
verticalArrangement = Arrangement.Top,
overflow = ContextualFlowRowOverflow.Clip,
modifier = Modifier,
) { index ->
Text(text = items[index].toString())
}
👉 Ключевое изменение в возможности получать
index
элемента, а так же lineIndex
, indexInLine
и maxWidthInLine
(maxHeightInLine
), maxHeight
(maxWidthin
) из ContextualFlowRowScope
(ContextualFlowColumnScope
)👉 Вы могли заметить, что теперь можно указать максимальное количество элементов, а это значит что в элемент можно накинуть на 1 больше элемент чем мы разрешили. Что произойдет? Сработает 1 из 4 overflow policy:
Clip,
Visible,
expandIndicator,
expandOrCollapseIndicator
, где вам отдается контроль над этими элементамиThis media is not supported in your browser
VIEW IN TELEGRAM
Порядок применения модификаторов в
👉 Хорошая привычка, прописывать
👉 Модификаторы применяются в порядке "от конца к началу, изнутри наружу"
👉 Примеры кода в статье
Composable
компонентах👉 Хорошая привычка, прописывать
Modifier
для каждой @Composable
функции👉 Модификаторы применяются в порядке "от конца к началу, изнутри наружу"
👉 Примеры кода в статье
Дебажим зависимости в Gradle!
Гайд о том как дебажить дерево зависимостей проекта на предмет коллизий
👉 Базово построить дерево зависимостей можно, но скорее всего оно будет нечитаемым
Добавив
👉 Это же дерево зависимостей лучше всего отфильтровать по конфигурации с помощью
👉 Найдя проблемную зависимость, разбираем ее с помощью dependencyInsight. Вы увидите как и почему выбирается та или иная версия для проекта.
А что дальше? В статье исключается транзитивная зависимость из одной из библиотек, тем самым решая изначальную проблему конфликта при обновлении фреймворка
Гайд о том как дебажить дерево зависимостей проекта на предмет коллизий
👉 Базово построить дерево зависимостей можно, но скорее всего оно будет нечитаемым
./gradlew :app:dependencies > dependencyTree.txt
Добавив
--scan
, можно посмотреть на аккуратную версию в браузере👉 Это же дерево зависимостей лучше всего отфильтровать по конфигурации с помощью
--configuration
. Они бывают: compileClasspath
, runtimeClasspath
, testCompileClasspath
, и testRuntimeClasspath
👉 Найдя проблемную зависимость, разбираем ее с помощью dependencyInsight. Вы увидите как и почему выбирается та или иная версия для проекта.
А что дальше? В статье исключается транзитивная зависимость из одной из библиотек, тем самым решая изначальную проблему конфликта при обновлении фреймворка
Не успели мы перейти на Kotlin 2, как Kotlin 2.0.20-Beta1 приносит новые изменения. Функция
Как будет выглядеть:
Используете ли вы приватный конструктор у data классов?
copy()
для data class
будет иметь ту же видимость, что и конструктор. В бета версии пока что покажут warning при использованииКак будет выглядеть:
data class PositiveInteger private constructor(val number: Int) {
companion object {
fun create(number: Int): PositiveInteger? = if (number > 0) PositiveInteger(number) else null
}
}
fun main() {
val positiveNumber = PositiveInteger.create(42) ?: return
// Будет вызывать Warning в 2.0.20-Beta1
val negativeNumber = positiveNumber.copy(number = -1)
// warning: non-public primary constructor is exposed via the generated 'copy()' method of the 'data' class.
}
Используете ли вы приватный конструктор у data классов?
Появились записи с KotlinConf, разбитые на части:
https://kotlinconf.com/talks/
Особенно хочется отметить моих коллег, которые рассказали как устроено наше кросплатформенное приложение (KMM + Compose). Зацените, будет интересно: https://kotlinconf.com/talks/584799/
https://kotlinconf.com/talks/
Особенно хочется отметить моих коллег, которые рассказали как устроено наше кросплатформенное приложение (KMM + Compose). Зацените, будет интересно: https://kotlinconf.com/talks/584799/
This media is not supported in your browser
VIEW IN TELEGRAM
Спустя 4 года в беклоге, фича с заполнением обязательных параметров готова и будет доступна в IDEA 2024.2 EAP. До Android Studio докатится значительно позже.
Мне этого функционала очень давно не хватает
Мне этого функционала очень давно не хватает
Сегодня разберем частый и не очевидный паттерн -
Как выглядит:
Таким образом предоставляется только интерфейс наружу. Kotlin команда часто так делает, например
Зачем? Это дает свободу разработчикам подменять класс реализации без сложной и ломающей все миграции.
Из книги Marcin Moskała, Effective Kotlin
fake interface constructor
.Как выглядит:
interface Foo {
fun foo()
}
fun Foo(): Foo = object : Foo {
override fun foo() {
println("foo")
}
}
fun main() {
val foo: Foo = Foo()
foo.foo()
}
Таким образом предоставляется только интерфейс наружу. Kotlin команда часто так делает, например
Job, CoroutineScope, CompletableDeferred, Channel, Mutex, Semaphore, MutableStateFlow, MutableSharedFlow, List
именно так и реализованы. При инициализации вы обращаетесь к функции, что, например, сказывается на подсветке синтаксиса в IDE (вызов функции, а не обращение к конструктору)Зачем? Это дает свободу разработчикам подменять класс реализации без сложной и ломающей все миграции.
Из книги Marcin Moskała, Effective Kotlin
Что быстрее и в каких задачах. Корутины, RxJava или Executor!
👉 Большой анализ с помощью Jetpack Microbenchmark.
👉 Автор исследует как работают инструменты на единственном потоке, на максимальном количестве потоков исполняемых параллельно и на количестве потоков, равное количеству задач.
👉 Наглядно видно, почему стоит использовать встроенные IO диспатчеры для задач связанных с записью данных
👉 Автор приходит к выводу что лучше использовать малое количество потоков, дробя большую задачу на подзадачи, для быстрого выполнения
Код, соответсвующий результатам на графике, приведен ниже. Автор так же делает сравнительный анализ для каждой операции, так что рекомендую глянуть статью целиком!
👉 Большой анализ с помощью Jetpack Microbenchmark.
👉 Автор исследует как работают инструменты на единственном потоке, на максимальном количестве потоков исполняемых параллельно и на количестве потоков, равное количеству задач.
👉 Наглядно видно, почему стоит использовать встроенные IO диспатчеры для задач связанных с записью данных
👉 Автор приходит к выводу что лучше использовать малое количество потоков, дробя большую задачу на подзадачи, для быстрого выполнения
Код, соответсвующий результатам на графике, приведен ниже. Автор так же делает сравнительный анализ для каждой операции, так что рекомендую глянуть статью целиком!
private fun mixed(seed: Int): Int {
return when {
seed % 5 == 0 -> network(seed)
seed % 3 == 0 -> storage(seed)
seed % 2 == 0 -> listsManipulation(seed)
else -> arithmetic(seed)
}
}
Набор начинающего платформенного инженера
Попробовать капнуть поглубже, разобраться в кишках системы и собрать свой образ AOSP!
👉 Перво-наперво это конечно системные требования, они примерно соответствуют топовому MacBook Pro, если бы он был не arm.
👉 Зачем столько ядер? AOSP содержит примерно 150 000 файлов, которые лучше всего обрабатывать параллельно. Сюда же и ответ зачем нужна быстрая память
👉 Синхронизация внешних зависимостей проекта займет порядка 200-300 GB вашего интернет-траффика
👉 Можно выбрать для какого гуглового девайса вы хотите собирать систему тут
👉 После всех манипуляций, простой командой запускаем сборку
⌛️ Ждём, ждём, ждём
👉 C помощью
👉 Для удобства модификации исходников используется Android Studio for Platform. Это отдельная версия Android Studio, которую релизнули в этом году
👉 Можно запустить такой сетап где-нибудь в облаке, если у вас нет желания собирать отдельную станцию под это. Будет стоить денег, но, обычно, арендовать на день-другой стоит не дорого
Попробовать капнуть поглубже, разобраться в кишках системы и собрать свой образ AOSP!
👉 Перво-наперво это конечно системные требования, они примерно соответствуют топовому MacBook Pro, если бы он был не arm.
72 Core x86_64, 64GB DDR5, 400GB SSD NVMe
. Такой сетап соберет билд за 40 минут (по заверениям гугла). 6 ядерная машина же застрянет на 6 часов в сборке👉 Зачем столько ядер? AOSP содержит примерно 150 000 файлов, которые лучше всего обрабатывать параллельно. Сюда же и ответ зачем нужна быстрая память
👉 Синхронизация внешних зависимостей проекта займет порядка 200-300 GB вашего интернет-траффика
👉 Можно выбрать для какого гуглового девайса вы хотите собирать систему тут
👉 После всех манипуляций, простой командой запускаем сборку
source setup/buildenv.sh
👉 C помощью
adb
и fastboot
заливаем сборку в девайс и радуемся свежей операционке Android aka Good Reads
👉 Для удобства модификации исходников используется Android Studio for Platform. Это отдельная версия Android Studio, которую релизнули в этом году
👉 Можно запустить такой сетап где-нибудь в облаке, если у вас нет желания собирать отдельную станцию под это. Будет стоить денег, но, обычно, арендовать на день-другой стоит не дорого
Please open Telegram to view this post
VIEW IN TELEGRAM
Sid Patil
The Starter kit for Android Platform Engineering
Unlock the secrets of the Android Open Source Project (AOSP) with a comprehensive guide to Platform Engineering. This article covers everything from machine setup and IDE configuration to compiling a full Android system builds for Google Pixels.
123.gif
18.4 MB
Jetpack Glance
Многие делали виджеты для Android стандартными средствами. Теперь делаем с помощью Jetpack Compose. В статье можно подглядеть пример и сразу попробовать быстренько сверстать виджет для своего приложения.
Жаль, пока что есть поддержка только Android. Надеюсь, когда-нибудь будет и iOS
Документация https://developer.android.com/develop/ui/compose/glance
❗️ Помните! Лучше не смешивать
Многие делали виджеты для Android стандартными средствами. Теперь делаем с помощью Jetpack Compose. В статье можно подглядеть пример и сразу попробовать быстренько сверстать виджет для своего приложения.
Жаль, пока что есть поддержка только Android. Надеюсь, когда-нибудь будет и iOS
Документация https://developer.android.com/develop/ui/compose/glance
Composable
элементы виджета с существующими элементами. Они могут быть несовместимы с элементами из стандартной библиотекиPlease open Telegram to view this post
VIEW IN TELEGRAM
Про Server Driven UI.
Ранее автор разбирал ограничение Client Driven UI. А теперь продает нам преимущества SDUI.
👉 Как следует из названия, экраны отрисовываются по инструкциям с сервера
👉 Несмотря на кажущуюся независимость клиента от сервера, ваше приложение всё ещё будет ограничено существующими элементами
👉 Очень важный элемент — дизайн-система, которой следуют все приложения, иначе всё развалится
👉 A/B тесты, персонализация приложения под пользователя, обновление приложения на лету и независимый от сторов релиз-менеджмент — всё это вы получаете бонусом
👉 Сложность на Backend'е, невероятно долгая загрузка приложения, экспоненциально растущая сложность разработки и поддержки клиента — всё это вы также получаете бонусом c SDUI
Кто использует: Reddit, Tinder, AirBnB
Ранее автор разбирал ограничение Client Driven UI. А теперь продает нам преимущества SDUI.
👉 Как следует из названия, экраны отрисовываются по инструкциям с сервера
👉 Несмотря на кажущуюся независимость клиента от сервера, ваше приложение всё ещё будет ограничено существующими элементами
👉 Очень важный элемент — дизайн-система, которой следуют все приложения, иначе всё развалится
👉 A/B тесты, персонализация приложения под пользователя, обновление приложения на лету и независимый от сторов релиз-менеджмент — всё это вы получаете бонусом
👉 Сложность на Backend'е, невероятно долгая загрузка приложения, экспоненциально растущая сложность разработки и поддержки клиента — всё это вы также получаете бонусом c SDUI
Кто использует: Reddit, Tinder, AirBnB
Medium
Mastering SDUI: A Deep Dive into Server-Driven UI
What is Server-Driven UI (SDUI)?
Есть ли у вас опыт с Server Driven UI? Что думаете об этом подходе?
Final Results
6%
Первый раз слышу об этом
40%
Слышал ранее, но не применял
41%
Поработал на проекте где несколько экранов отрисовывались по инструкциям с сервера
16%
Был проект полностью в этом подходе