TGINSIGHT CHAT
Android Broadcast
@android_broadcast
TechnologiesПодборка новостей и статей для Android разработчиков. Реклама и связь с автором @ab_manager РКН https://abdev.by/rkn_tg_ab#MQRZR
Posts récents
Tag : #kotlin · 43 posts
Publié 28 avr.
🏝Вышла первая стабильная версия Metro DI — чистого Kotlin-решения с валидацией графа на этапе компиляции. Решение вобрало в себя всё самое лучшее от Dagger, Anvil и kotlin-inject, чтобы стать тем стандартом для KMP-проектов, который искали после Dagger. Metro DI не использует KSP или KAPT. Вся генерация осуществляется с помощью плагина компилятора Kotlin. #Kotlin#KMP#DI
Publié 2 avr.
⚡️R8 наконец-то починил AtomicReferenceFieldUpdater в корутинах на Android Это история про баг, которому больше двух лет. В 2023 году в трекере kotlinx.coroutines появился issue: AtomicReferenceFieldUpdater, которым корутины управляют состоянием Job, на Android работает в 2–4 раза медленнее, чем обычный AtomicReference на операциях compareAndSet и lazySet. Корень проблемы в том, что корутины используют atomicfu, который на JVM компилируется в Atomic*FieldUpdater ради совместимости с KMP. На десктопном JDK это нормально, но ART на Android оптимизирует их хуже. Бенчмарк на Pixel 4a давал 135 нс против 50 нс — разница почти в 3 раза на compareAndSet. R8 в составе AGP 9.2 закрывает этот разрыв на уровне компилятора: он определяет, где Atomic*FieldUpdater можно заменить на Unsafe-вызовы, и генерирует одну инструкцию вместо цепочки. ART тоже получит аналогичную оптимизацию в JIT, но она имеет ограничения по версии платформы и хуже масштабируется по тестам автора. Для нас это значит: никаких изменений в коде, просто обновить AGP. Бесплатное ускорение каждого launch и cancel в приложении. На мой взгляд, абсолютно правильно решать проблему именно на стороне R8, а не правками всех библиотек. 🔗 Источник - X Andrei Shikov #kotlin#coroutines#performance
Hashtags
Publié 28 janv.
🏝Когда стоит убить Kotlin демона для ускорения сборки Если у вас тяжёлая Android-сборка (много модулей, R8, CI с ограниченной памятью), имеет смысл принудительно завершать Kotlin Daemon после компиляции и до запуска R8 🔪 Kotlin Daemon нужен только на этапе компиляции Kotlin. После этого он спокойно живёт до конца сборки и держит память. R8 — один из самых прожорливых этапов по CPU и RAM 🔥 По итогу Daemon и R8 начинают конкурировать за ресурсы памяти Что вы реально получаете если убивает Kotlin демона после компиляции кода: 🚀 снижение пикового потребления памяти примерно на 13–15% 🚀 ускорение R8 вплоть до ~7% 🚀 небольшое, но стабильное сокращение общего времени сборки 🚀 максимальный эффект на CI, где нет долгоживущих демонов и инкрементальности ‼️ Этот подход сработал для автора статьи, но для вас может ничем и не помочь, особенно в сборке на локальной машине. 🔗Источник с измерениями и подробным разбором #Android#Kotlin#R8#Gradle
Publié 22 déc.
🤖Улучшаем работу со Stacktrace в Jetpack Compose (особенно в релизе) Команда Compose представила opt-in API для улучшения читаемости стектрейсов во время разработки и для релизов. Теперь становится возможным: 👉 Точно определять источник крешей в композиции, Side Effect (LaunchedEffect, DisposableEffect) и корутинах из rememberCoroutineScope. 👉 Изолировать падения для создания воспроизводимых примеров. 👉 Изучать креши, которые раньше показывали только внутренние фреймы Compose. Достаточно добавить одну строку в точке входа в приложение (например, в Application.onCreate()): // Включить stack trace только для минифицированных сборок (рекомендуемый способ) Composer.setDiagnosticStackTraceMode(ComposeStackTraceMode.Auto) // Или для локальной отладки (более точные, но тяжёлые трассировки) Composer.setDiagnosticStackTraceMode(ComposeStackTraceMode.SourceInformation) ‼️ВАЖНО Требуется Kotlin 2.3.0, а для режимов `Auto` и `GroupKeys` - включённый R8 с минификацией. Есть несколько режимов работы ✔️Auto (рекомендуется): использует GroupKeys для минифицированных сборок и None для отладочных. 👉GroupKeys: для минифицированных приложений. Использует маппинг-файл от R8 для восстановления примерного местоположения. 👉SourceInformation: для отладки. Даёт точные строки где произошел креш, но затратно по производительности. Стоит использовать только на этапе разработке. ❌None: ничего не добавляет (поведение по умолчанию). Под капотом любой креш в Compose коде оборачивается в DiagnosticComposeException, который добавляется в suppressed-исключения. В нём будет полная иерархия вызовов `@Composable` функций на момент падения! java.lang.IllegalStateException: Test layout error at <original trace> Suppressed: androidx.compose.runtime.DiagnosticComposeException: Composition stack when thrown: at ReusableComposeNode(Composables.kt:<unknown line>) at Layout(Layout.kt:79) at <lambda>(TempErrorsTest.kt:164) <-- Ваша функция! ... и т.д. ⚠️ Известные ограничения: 👉 В режиме SourceInformation для первых фреймов могут не указываться номера строк (<unknown line>). 👉GroupKeys указывает только на первую строку @Composable функции. 👉 Если сам сбор стектрейса упадёт, его исключение будет добавлено как suppressed. Подробнее в официальной документации 💬 А вы уже пользовались этой фичей? Делитесь в комментариях! 👇 #AndroidDev#Kotlin#Compose#R8#Android
Publié 17 déc.
🏝Kotlin 2.3.0 Stable! Вышла новая версия языка Команда Kotlin выпустила финальную версию Kotlin 2.3.0. Обновление приносит новые стабильные возможности языка, улучшения производительности и поддержку новейших инструментов. 📢 Основные нововведения: ✅ Язык: Больше стабильных функций, проверка неиспользуемых возвращаемых значений, явные backing field. ✅ Kotlin/JVM: Поддержка Java 25. ✅ Kotlin/Native: Улучшенный Swift export, ускорение сборки, импорт C/Objective-C библиотек (бета). ✅ Kotlin/Wasm: Полные имена и новая модель исключений включены по умолчанию. ✅ Kotlin/JS: Экспериментальный export suspend-функций, новое представление LongArray. ✅ Gradle: Совместимость с Gradle 9.0, новый API для регистрации сгенерированных исходников. ✅ Compose compiler: Стектрейсы для минифицированных Android-приложений. ✅ Стандартная библиотека: Стабильные API для работы со временем и улучшенная работа с UUID. 📖 Подробнее на сайте Каждую ключевую фичу подробно разберу в отдельном посте в канале @kotlin_broadcast. Следите за новостями! #Kotlin
Hashtags
Publié 15 déc.
🛠IntelliJ IDEA теперь единая: больше бесплатных функций и упрощенный выбор JetBrains объявила о важном изменении: с версии 2025.3 IntelliJ IDEA Community Edition и Ultimate объединяются в один продукт. Больше не нужно выбирать между двумя редакциями. Всё основное — бесплатно: Базовый функционал для разработки на Java, Kotlin, поддержка Spring Boot, работа с базами данных и многое другое доступны сразу после установки без активации. Важно: 1️⃣Станет проще: Не нужно переустанавливать IDE, чтобы перейти с бесплатной версии на платную или обратно. 2️⃣30-дневный пробный период Ultimate: Все расширенные инструменты (профилировщики, продвинутая веб-поддержка, фреймворки Enterprise) можно бесплатно протестировать. 3️⃣Открытый код: Исходный код IDE по-прежнему доступен на GitHub для сборки 4️⃣Пользователи Community Edition: При обновлении до 2025.3 получите единую IDE со всеми бесплатными функциями и пробным периодом Ultimate (если вам надо). 5️⃣Пользователи Ultimate: Лицензия автоматически конвертируется в подписку. Если она истечёт, вы не потеряете доступ к IDE — просто останетесь на базовом функционале JetBrains уже ранее закрыла Fleet. Кажется, что все шаги идут как оптимизация портфолио продуктов и упрощение разработки. #JetBrains#IDEA#IDE#Java#Kotlin
Hashtags
Publié 1 déc.
📹Введение в FlowMVI FlowMVI - простая и эффективная библиотека для реализации MVI подхода в Android и Kotlin Multiplatform приложениях. Из видео вы узнаете про возможности бибилотеки и интеграцию ее в проект. Автор библиотеки Никита @nek_12 сделал серию видео с демонстрацией возможностей. Все видео будут доступны на YouTube и VK Video, а автору очень нужна ваша поддержка и обратная связь в комментариях под видео (а не этим постом). #MVI#Архитектура#KMP#Kotlin#Кодинг
Publié 28 nov.
🤖Как обработать слишком быстрый ввод пользователя с помощью Coroutines Flow Если внимательно посмотреть на поведение людей в поисковых полях, становится понятно: пальцы работают быстрее, чем приложение успевает реагировать. Пользователь печатает «a», тут же «an», следом «and» — а приложение в панике пытается перестроить результаты после каждого шага. Поток начинает «стрелять» событиями, система перегружается, а интерфейс выглядит так, будто его кто-то перематывает на ускоренной перемотке. Главная проблема здесь не скорость человека — а то, что приложение воспринимает каждую мелочь как повод что-то пересчитать. Чтобы интерфейс работал предсказуемо, нужно научить поток реагировать не на каждое изменение, а на осмысленное завершение ввода. ⏳Зачем нужен debounce() Оператор debounce() работает как фильтр слишком быстрых изменений: - быстрые изменения подряд — игнорируются - устойчивое значение после паузы — двигаются по потоку дальше Поток перестаёт реагировать на каждую букву и начинает слушать устойчивые состояния строки. val results = queryFlow .debounce(300) // значение задержки можно менять .distinctUntilChanged() .map { term -> searchData(term) } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList()) ------------ Помимо полезных символов, пользователь может случайно добавить пробел в конце или другой невидный символ. Фактически это тот же запрос — но без обработки поиск запустится повторно. В таких случаях можно определиться как оператор distinctUntilChanged() будет сранивать значения: queryFlow .debounce(300) .distinctUntilChanged { old, new -> old.trim() == new.trim() } Теперь оба состояния считаются одинаковыми, и поиск не перезапускается зря. #kotlin#coroutines#flow#android
Hashtags
Publié 21 nov.
🚀Navigation Event 1.0.0 — новая KMP-библиотека для обработки навигации на разных платформах Что дает библиотека 👉 Единый кроссплатформенный API для замены разрозненных решений 👉 Централизованная система управления всей навигацией в приложении 👉 Базовый слой для будущих навигационных решений Android Пример использования: val myHandler = object : NavigationEventHandler<NavigationEventInfo>( initialInfo = CurrentInfo, isBackEnabled = true ) { override fun onBackStarted(event: NavigationEvent) { // Подготовка к навигации } override fun onBackProgressed(event: NavigationEvent) { // Анимации на основе event.progress } override fun onBackCompleted() { // Завершение навигации } } 👉 Готовая интеграция с Compose val navEventState = rememberNavigationEventState( currentInfo = CurrentInfo, backInfo = PreviousInfo ) NavigationBackHandler( state = navEventState, isBackEnabled = true, onBackCompleted = { /* Действие при завершении */ } ) 👉 Диспетчеры могут образовывать родительско-дочерние цепочки: // Compose val childDispatcher = rememberNavigationEventDispatcher( parent = LocalNavigationEventDispatcherOwner .current .navigationEventDispatcher ) 👉 Нативная поддержка Predictive Back из Android 👉 Библиотека уже используется в Activity 1.12.0 как базовый слой #Jetpack#Navigation#Compose#KMP#PredictiveBack#Kotlin
Publié 20 nov.
🚀Lifecycle 2.10.0 вышел в стабильной версии! Google выпустила мажорное обновление библиотек Lifecycle. Этот релиз сфокусирован на улучшении интеграции с Compose. ⚙️rememberLifecycleOwner для Compose Новый композабл позволяет создавать изолированные LifecycleOwner внутри UI. Идеально для компонентов, которым нужно независимое управление состоянием — например, для HorizontalPager, где только активная страница должна быть в состоянии RESUMED. @Composable fun MyComposable() { val lifecycleOwner = rememberLifecycleOwner( maxLifecycle = Lifecycle.State.RESUMED, parentLifecycleOwner = LocalLifecycleOwner.current, ) CompositionLocalProvider( LocalLifecycleOwner provides lifecycleOwner ) { // Дочерние композаблы теперь имеют собственный жизненный цикл } } 🚀 Интеграция с Navigation 3 Новый артефакт lifecycle-viewmodel-navigation3 предоставляет готовый декоратор для автоматической привязки ViewModel к отдельным экранам в Navigation 3. NavDisplay( backStack = backStack, entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), rememberViewModelStoreNavEntryDecorator(), // Добавляем эту строку ), entryProvider = entryProvider { /* ... */ } ) Удобства для разработчиков: 👉 Идиоматичный Kotlin API для создания кастомных CreationExtras CreationExtras { this[MY_CUSTOM_KEY] = "myValue" } 👉 Метод savedStateHandle.saved() теперь нативно поддерживает nullable типы 👉Конструкторы SavedStateHandle помечены как @VisibleForTesting ⚠️ Важное изменение Повышение minSdk с API 21 до API 23 — убедитесь, что ваше приложение соответствует новым требованиям. #Jetpack#Lifecycle#Compose#Navigation#ViewModel#Kotlin
Publié 20 nov.
🚀Вышла стабильная версия Jetpack DataStore 1.2 Google выпустила долгожданный стабильный релиз DataStore 1.2.0. Эта версия приносит несколько важных улучшений, которые делают библиотеку ещё более мощной и удобной, особенно для проектов, не полностью перешедших на Kotlin Coroutines. Ключевые нововведения: ✅Поддержка Guava Появился новый модуль datastore-guava, который предоставляет API на основе ListenableFuture для разработчиков, использующих Guava. Теперь подключать DataStore в проекты на Java стало намного проще (а нужно было???) // Пример использования GuavaDataStore val guavaDataStore: DataStore<Preferences> = GuavaDataStore.from( produceFile = { context.preferencesDataStoreFile("settings.pb") }, serializer = PreferencesSerializer, executor = Dispatchers.IO.asExecutor() // Используем Executor ) ListenableFuture<Preferences> future = guavaDataStore.getData(); ✅ Мультипроцессность для GuavaDataStore Функциональность многопроцессного доступа, ранее доступная для Kotlin-версии, теперь добавлена и в GuavaDataStore. ✅Поддержка Android Direct Boot - работа приложений до разблокировки устройства DataStore теперь можно безопасно использовать в режиме Direct Boot. Для этого данные нужно разместить в защищённом хранилище устройства (Device Protected Storage). val directBootDataStore = DataStoreFactory.createInDeviceProtectedStorage( serializer = PreferencesSerializer ) { context.preferencesDataStoreFile("direct_boot_settings.pb") } ✅ Исправления важных багов 👉 Устранен UnsatisifedLinkError при использовании R8 без стандартного ProGuard-файла. 👉 Исправлена проблема, из-за которой операции GuavaDataStore могли запускаться на главном потоке вместо указанного IO-диспетчера. 👉 Решена проблема с FileNotFoundException в OkioStorage при одновременном обращении к файлу (добавлена вторая попытка чтения). Прочие улучшения 👉 Добавлен PreferencesFileSerializer — готовый сериализатор для работы с FileStorage. #Android#Jetpack#DataStore#Kotlin#Java#Guava
Publié 19 nov.
🏝Stacktrace-decoroutinator - библиотека для восстановления стектрейса ошибок, связанных с Kotlin Coroutines. Работает с Android 14+ и Java 8 и выше Для работы в Android надо подключить Gradle плагин plugins { id("dev.reformator.stacktracedecoroutinator") version "2.5.8" } #android#kotlin#coroutines
Hashtags