Forwarded from Android Good Reads
Strong Skipping Mode не делает типы stable, лишь позволяет skip’ать
Внутри много кода, а не воды для самопроверки
composable с unstable параметрами, если передан тот же самый объект по ссылке ===, тогда как stable типы по-прежнему сравниваются через equals() из-за этого он не помогает, если создаются новые инстансы (типа listOf(), copy()), и рекомпозиция всё равно происходит, поэтому stability позволяет пропускать перерисовку для разных объектов с одинаковыми данными, а Strong Skipping - это оптимизация для случаев с переиспользованием одной и той же ссылки, а не замена пониманию стабильностиВнутри много кода, а не воды для самопроверки
Forwarded from Mobile Compose
This media is not supported in your browser
VIEW IN TELEGRAM
#Compose #UI #Animation #Debugging
🎨 Compose 1.11.0 — Визуальная отладка анимаций
Shared Elements анимации и работа с Modifier.animatedBounds стали прозрачнее благодаря инструменту LookaheadAnimationVisualDebugging.
Ключевые возможности:
▫️ Прямо в Runtime можно увидеть траектории движения объектов и их целевые границы (target bounds).
▫️ Визуализация помогает понять, почему элемент «прыгает» или обрезается при переходе между экранами.
Инструмент полезен в первую очередь для сложных UI-переходов, где раньше приходилось полагаться только на логи и интуицию.
🎨 Mobile Compose 💬 Чат канала
♾
Shared Elements анимации и работа с Modifier.animatedBounds стали прозрачнее благодаря инструменту LookaheadAnimationVisualDebugging.
Ключевые возможности:
Инструмент полезен в первую очередь для сложных UI-переходов, где раньше приходилось полагаться только на логи и интуицию.
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Compose Broadcast
This media is not supported in your browser
VIEW IN TELEGRAM
#Compose
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Compose Broadcast
// Пример использования
LookaheadAnimationVisualDebugging(
overlayColor = Color(0x4AE91E63),
isEnabled = true,
multipleMatchesColor = Color.Green,
isShowKeylabelEnabled = false,
unmatchedElementColor = Color.Red,
) {
SharedTransitionLayout {
CompositionLocalProvider(
LocalSharedTransitionScope provides this,
) {
// your content
}
}
}
#Compose
Forwarded from Compose Broadcast
До недавнего времени стилизация компонентов в Compose делалась через параметры Composable функции (
color = ..., padding = ...) или модификаторы. Это работало, но могло приводить к:👉 избыточным рекомпозициям при смене состояний;
👉 дублированию кода для разных вариаций кнопок/карточек;
👉 сложностям с анимацией переходов между стилями.
Google представил Styles API (экспериментальный, о причинах такого статуса ниже) — новый подход, вдохновлённый CSS. Нужен Jetpack Compose 1.11.0 или свежее
Ключевые возможности
Стили вычисляются на этапах layout и drawing, минуя composition. Это значит, что изменение стиля (например, при наведении) не вызывает рекомпозицию родительских компонентов.
Без кучи
if/else и animate*AsState. Просто описываете стиль для каждого состояния (нажат, сфокусирован, включён, ошибка и т.д.).Переходы между состояниями анимируются автоматически с физическими параметрами (демпфирование, жёсткость). Не нужно писать
Animatable или Transition.// Пример использования стиля
// Определяем стиль для кнопки
val buttonStyle = Style {
default {
backgroundColor = Color.Blue
shape = RoundedCornerShape(8.dp)
}
pressed {
backgroundColor = Color.DarkBlue
scale = 0.98f
}
disabled {
backgroundColor = Color.Gray
alpha = 0.5f
}
}
// Используем
Button(
onClick = { /* ... */ },
style = buttonStyle, // ← вместо кучи параметров
enabled = isEnabled
) {
Text("Нажми меня")
}
style — новый параметр, который появляется у всех компонентов Material 3 и базовых (Box, Row, Column).⚠️ Styles API не заменяет модификаторы
Модификаторы остаются для позиционирования, кликов, размеров. Styles API заменяет только внутреннюю стилизацию (цвета, формы, тени, отступы внутри компонента). Это как разделение «темы» и «вёрстки».
API остаётся экспериментальным пока на него полностью не перейдет Material 3 Compose, чтобы учесть все необходиcмоти API и не делать breaking changes. По работе оно уже стабильно, но вот изменения в коде, возможно, будут.
🔗 Официальная документация
В целом с таким подходом уже привыкли работать в Android XML Layout, то почему бы сразу было его не использовать? Тем более в Compose плюсы очевидны!
#Compose #Material
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Kotlin Multiplatform Broadcast
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Good Reads
This media is not supported in your browser
VIEW IN TELEGRAM
Compose анимации без пересборки
Дебажить анимации трудно и долго. Hot reload помогает и тут. Внутри анимация
Дебажить анимации трудно и долго. Hot reload помогает и тут. Внутри анимация
Grid, кастомная анимация волны на Canvas, изменение типа анимации tween -> spring, изменение animateContentSizeHotSwan обновляет примитивы в обход компиляции Gradle, за счет этого и получается такой результатForwarded from Android Broadcast
🤯 Те кто использовал Jetpack Paging 3 знают насколько он может справиться только с базовыми сценариямми. Шаг влево или вправо - уже боль!
Сегодня хочу познакомить вас с альтернативой — библиотекой🐱 Paginator. Это KMP-решение для пагинации, которое решает те самые проблемы, где Paging 3 начинает "буксовать".
Paginator построен на отличной модели от Jetpack Paging 3: страница — это адресуемая ячейка в кэше, кэш — обычная структура данных, а навигация — обычные методы.
1️⃣ ✅ Адресуемые страницы
Прямые методы
2️⃣ ✅ Мутации по запросу
3️⃣ ✅ Сохраняемое состояние
Кэш — обычная структура данных, которую можно сериализовать через
4️⃣ ✅ Библиотека, а не фреймворк
Написан на чистом Kotlin без платформенных зависимостей и живёт в
5️⃣ ✅ Курсорная пагинация "из коробки"
Отдельный класс
🔗 Оригинальная статья на Хабре
🐱 Репозиторий Paginator
#Android #AndroidDev #KMP
Сегодня хочу познакомить вас с альтернативой — библиотекой
Paginator построен на отличной модели от Jetpack Paging 3: страница — это адресуемая ячейка в кэше, кэш — обычная структура данных, а навигация — обычные методы.
Прямые методы
goNextPage(), goPreviousPage() и jump(Bookmark). Deeplink на сообщение из пуша решается одной строкой.MutablePaginator предоставляет CRUD-операции: replace { it.id == 42 }, removeWhere { it.deleted }. Один лайк меняет один элемент без инвалидации всей страницы.Кэш — обычная структура данных, которую можно сериализовать через
kotlinx.serialization. Методы serializeToJson() и restoreFromJson() решают проблему Process Death без плясок с бубном.Написан на чистом Kotlin без платформенных зависимостей и живёт в
commonMain. Логика пагинации становится частью общего доменного слоя KMP, не копируется между платформами и не имеет двух реализаций.Отдельный класс
CursorPaginator с единой моделью состояний, транзакций и сериализации.Paginator — это не обёртка над Paging 3. Это другая модель, переосмысливающая ключевые типы. Обёртка просто не смогла бы дать ни мутации элемента, ни сериализации кэша.
🔗 Оригинальная статья на Хабре
#Android #AndroidDev #KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
NoSuchMethodError или ClassNotFoundException, знакома многим. Причина — тихий конфликт версий. Gradle по умолчанию старается брать самую новую версию из всех найденных, но срабатывает не всегда. В разных модулях одного проекта могут спокойно жить разные версии одной библиотеки (например, okhttp 4.9.0 в модуле А и 4.11.0 в модуле Б). Gradle не считает это конфликтом, потому что модули изолированы. В рантайме при передаче объекта между модулями — ClassCastException. Особенно больно это бьет в KMP, где общая бизнес-логика связывает всё в единую цепочку.Плагин
# Пример работы плагина
Version conflict detected: org.slf4j:slf4j-api
- version 2.0.17 via:
- project :app -> ch.qos.logback:logback-classic:1.4.11 -> org.slf4j:slf4j-api:2.0.17
...
- version 1.7.25 via:
- project :app -> org.apache.logging.log4j:log4j-slf4j-impl:2.17.1 -> org.slf4j:slf4j-api:1.7.25
Такая проактивная проверка помогает фиксить конфликты еще на этапе разработки и писать более стабильный код. Попробуйте.
#Gradle
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
Данные официального бенчмарка Google
#AI #Benchmark
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Good Reads
Android CLI зацикливает на себе весь цикл разработки для андроид c агентами. Вам не нужно прыгать и искать какие скилы подтянуть в проект, какой контекст по андроид разработке предоставить. All-in-one от гугла (sdk, эмуляторы, запуск билдов ... )
Ни для чего другого, кроме как мобильной разработке, это не подходит, так что поставить точно рекомендую!
Ни для чего другого, кроме как мобильной разработке, это не подходит, так что поставить точно рекомендую!
Forwarded from Антоха Разраб про AI
This media is not supported in your browser
VIEW IN TELEGRAM
Все идет по пути к тому что у каждого тула будет CLI версия. Обсидиан запустил пару месяцев назад, а вот и Google (Пере)представляет Android CLI
По ощущениям оч кастрированный и является надстройкой над
(c) Антоха Разраб про AI
По ощущениям оч кастрированный и является надстройкой над
adb(c) Антоха Разраб про AI
Forwarded from Android Good Reads
Если вы используете Metro, в качестве DI, то знайте что оно стало стабильным. Свеженаписанный легковесный DI для android
Релиз ноутс: https://github.com/ZacSweers/metro/releases/tag/1.0.0
Релиз ноутс: https://github.com/ZacSweers/metro/releases/tag/1.0.0
Forwarded from Android Good Reads
Что нового в Compose в Апреле
👉 v2 API тестирования стал дефолтным,
👉 Shared Elements: новый composable
👉 Поддержка трекпадов: теперь трекпады распознаются как
👉 Compose runtime: новый
👉 Аннотация
👉 Готовимся что в 1.12.0
Android Good Reads
compose-bom:2026.04.01 или Compose 1.11.0👉 v2 API тестирования стал дефолтным,
StandardTestDispatcher вместо UnconfinedTestDispatcher. Коррутины в тестах больше не выполняются сразу — очередь, пока виртуальные часы не продвинутся👉 Shared Elements: новый composable
LookaheadAnimationVisualDebugging показывает границы анимаций, траектории и несовпадения👉 Поддержка трекпадов: теперь трекпады распознаются как
PointerType.Mouse, а не Touch. Исправляет скролл вместо выделения, добавляет поддержку жестов и десктопных контекстных меню👉 Compose runtime: новый
HostDefaultProvider позволяет библиотекам (особенно KMP) получать сервисы без зависимости от compose-ui👉 Аннотация
@PreviewWrapper для переиспользуемых обёрток превью:class ThemeWrapper: PreviewWrapper {
@Composable
override fun Wrap(content: @Composable (() -> Unit)) {
JetsnackTheme {
content()
}
}
}
@PreviewWrapperProvider(ThemeWrapper::class)
@Preview
@Composable
private fun ButtonPreview() {
// JetsnackTheme in effect
}👉 Готовимся что в 1.12.0
compileSdk обновится до 37. Будет много боли потому что 37 Sdk тянет за собой AGP 9Android Good Reads
Forwarded from Android Good Reads
Что нового в Compose в Апреле Часть 2
Экспериментальные API:
👉 Styles API: декларативные стили компонентов с автоматическими анимациями. Судя по бенчмаркам, быстрее модификаторов
👉 MediaQuery: адаптация под окружение (размер окна, тип клавиатуры, режим стола и т.д.)
👉 Grid: 2D-раскладка с треками, фракциями (fr) и авто-размерами
👉 FlexBox: мощный контейнер с гибким распределением пространства, wrap'ом и выравниванием. Замена Row/Column/Flow
👉 Новый
Android Good Reads
Экспериментальные API:
👉 Styles API: декларативные стили компонентов с автоматическими анимациями. Судя по бенчмаркам, быстрее модификаторов
👉 MediaQuery: адаптация под окружение (размер окна, тип клавиатуры, режим стола и т.д.)
👉 Grid: 2D-раскладка с треками, фракциями (fr) и авто-размерами
👉 FlexBox: мощный контейнер с гибким распределением пространства, wrap'ом и выравниванием. Замена Row/Column/Flow
👉 Новый
SlotTable: ускорение случайных правок в дереве композиции (пока опционально через флаг)Android Good Reads
Forwarded from Compose Broadcast
В апрельском релизе Jetpack Compose под номером 1.11 в compose-runtime завезли четыре новых API:
HostDefaultProvider, LocalHostDefaultProvider, HostDefaultKey и ViewTreeHostDefaultKey. Плюс билдер compositionLocalWithHostDefaultOf для авторов библиотек.Он позволяют объявить
CompositionLocal, у которого дефолтное значение резолвится из окружения хоста — например, через Android View tag'и (как это делает ViewTreeLifecycleOwner или ViewTreeOnBackPressedDispatcherOwner). Раньше для такого паттерна была обязательна зависимость на compose-ui. Теперь только compose-runtime.Раньше чтобы из библиотеки достать значение из View tree, приходилось тянуть compose-ui ради LocalView и платформенные функции поиска по дереву View. Код жил в Android-сорсах, в commonMain такое не положишь:
// androidMain — compose-ui + Android-only API
val LocalMyOwner = compositionLocalOf<MyOwner?> { null }
@Composable
fun ProvideMyOwner(content: @Composable () -> Unit) {
val view = LocalView.current
val owner = remember(view) {
view.findViewTreeMyOwner()
}
CompositionLocalProvider(LocalMyOwner provides owner) {
content()
}
}
С новым API описание CompositionLocal живёт в commonMain и тянет только compose-runtime. Связку с View tree описывает ViewTreeHostDefaultKey, и хост сам отдаёт значение через своего провайдера:
// commonMain — только compose-runtime
val MyOwnerKey = ViewTreeHostDefaultKey<MyOwner>(
viewTagId = R.id.view_tree_my_owner
)
val LocalMyOwner = compositionLocalWithHostDefaultOf(MyOwnerKey)
// Использование — без изменений
@Composable
fun MyComponent() {
val owner = LocalMyOwner.current
// ...
}
Теперь авторы Compose библиотек могут держать определение CompositionLocal в общем модуле без зависимости на compose-ui. Профит - меньше транзитивных зависимостей в KMP-библиотеках и более чистое разделение слоёв runtime и UI.
#Compose #CMP
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Compose Broadcast
Главные фичи:
Breaking изменения, которые заденут почти всех:
👉 Минималка Kotlin поднята до 2.3.10
👉 Минимальная iOS теперь 14 (поддержка 13 ушла)
👉 iosX64 и macosX64 удалены полностью
👉 Shader на не-Android стал wrapper-классом
Я ждал нативный input на iOS с того момента, как Compose туда заехал. Текущая реализация на Skia всегда чувствовалась чужой на ощупь, особенно при сложном выделении и системных меню. Надо пробовать!
#compose #cmp #kotlin
Please open Telegram to view this post
VIEW IN TELEGRAM
Навигация во Flutter сначала кажется автору простой: push и pop. Но по мере роста проекта появляются табы, вложенные модули, диплинки — и каждый экран начинает открываться по-своему, а
pop() ведёт себя непредсказуемо.Navigator 1.0 прост, но не масштабируется. Navigator 2.0 даёт контроль, но требует тонны бойлерплейта. Пакеты вроде
go_router (режим поддержки) и auto_route (кодогенерация) решают часть проблем, но не все.Автор и его команда прошли через все эти варианты в Яндекс Про — приложении с сотнями фич, несколькими командами и вложенной навигацией. Так появился
yx_navigation — новый пакет в экосистеме архитектурных решений для Flutter, следующий после yx_scope (DI) и yx_state (управление состоянием).В статье автор расскажет, с какими трудностями столкнулась команда, какие требования сформулировала, как устроен
yx_navigation сегодня и как именно он решает проблемы крупных приложений.#свежак #Flutter
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Kotlin Multiplatform Broadcast
Раньше всё было в одном composeApp, который одновременно был и KMP библиотекой, и приложением. Это создавало путаницу в build конфигах и платформенных настройках. iOS при этом уже жил в отдельной папке, и асимметрия торчала наружу.
Главным триггером изменений стал Android Gradle Plugin 9, который больше не позволяет применять Android application plugin к multiplatform модулю. Entry point Android приложения теперь обязательно вынесен в отдельный модуль.
Если в проекте есть нативный UI (например, SwiftUI для iOS), shared разбивается на два модуля:
sharedLogic без Compose зависимостей и sharedUI только для платформ с Compose Multiplatform. Для проектов с серверной частью добавляется server модуль и core с общими моделями и валидацией для шаринга между клиентом и сервером.Я ещё до этого держал каждый application в отдельном модуле, так что для меня новая дефолтная структура лишь оформляет то что уже стало здравым смыслом. Раньше с одним shared было неприятно из-за того что Kotlin stdlib и зависимости тащились в каждый iOS framework. Несколько атомарных shared модулей решают эту проблему и позволяют точечнее управлять тем что попадает на каждую платформу. Очень рад что JetBrains двигаются в сторону более атомарных модулей, но пока есть вопросы не будет ли дублирования базовых Kotlin библиотека в каждый Xcode фреймворк.
Новая структура уже доступна в KMP wizard на kmp.new и в IDE плагине.
🔗 Анонс
#Kotlin #KMP #Gradle
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
‼️ Android View всё! Да здравствует Compose!
Google официально объявила о переходе к стратегии «Compose-first» и прекращении развития Android View, переводя его в режим поддержки.
Что это значит:
👉 Классы android.widget.* в Android SDK будут находиться в режиме поддержки.
👉 Библиотеки Android Jetpack про кастомные View (включая RecyclerView) также переходят в режим поддержки.
👉 Все инструменты в Android Studio будут создаваться только для Compose.
👉 Документация будет писаться только для Compose, однако некоторые разделы про View останутся.
🔗 Источник - оф сайт Android Developers
#Android #AndroidDev #Compose
Google официально объявила о переходе к стратегии «Compose-first» и прекращении развития Android View, переводя его в режим поддержки.
Что это значит:
👉 Классы android.widget.* в Android SDK будут находиться в режиме поддержки.
👉 Библиотеки Android Jetpack про кастомные View (включая RecyclerView) также переходят в режим поддержки.
👉 Все инструменты в Android Studio будут создаваться только для Compose.
👉 Документация будет писаться только для Compose, однако некоторые разделы про View останутся.
🔗 Источник - оф сайт Android Developers
#Android #AndroidDev #Compose
Forwarded from Android Broadcast
👉 CardView
👉 ConstraintLayout
👉 CoordinatorLayout
👉 CustomView
👉 Databinding
👉 DragAndDrop
👉 DrawerLayout
👉 DynamicAnimation
👉 Emoji
👉 Fragment
👉 GridLayout
👉 Interpolator
👉 Loader
👉 Navigation
👉 PercentLayout
👉 Preference
👉 RecyclerView
👉 SlidingPaneLayout
👉 SwipeRefreshLayout
👉 Transition
👉 VectorDrawable
👉 ViewPager
👉 ViewPager2
👉 Material Design Components (Views)
Считаю что делать так с RecyclerView поступили опрометчиво, ведь не все возможности может сделать Lazy*** Composable, а вот на Fragment и подавно куча приложений строится. Но нам дадут волшебные скиллы для миграции по одному экрану за раз
#Android #AndroidDev #Compose #
Please open Telegram to view this post
VIEW IN TELEGRAM