Kotlin Adept Notes
2.33K subscribers
80 photos
9 videos
131 links
Канал о разработке на Kotlin и обо всем, что с ним связано
По всем вопросам и рекламе: @ajiekcx
Download Telegram
Розыгрыш билета на Подлодку

Мы с командой в очередной раз подготовили для вас новый сезон Podlodka Android Crew, который стартует уже 15 сентября.

В этот раз будем говорить про архитектуру, которая выходит за рамки экранов и навигации.

В программе:

🟢Бинарная совместимость. Абакар Магомедов расскажет всё про бинарную совместимость: что это такое и как её соблюдать при разработке собственной библиотеки.

🟢Интервью с мобильным архитектором. Вместе с Эдуардом Некрутовым узнаем, чем занимается архитектор мобильных приложений. Разберём реальные кейсы, типичные задачи и главные вызовы этой роли.

🟢Архитектура Ktor для Android-разработчика. Разработчик библиотеки Ktor Осип Фаткуллин расскажет, как устроена библиотека под капотом, и покажет, как проектировать расширения для неё.

🟢Что лежит под капотом удобного SDK? Игорь Рыбаков рассмотрит лучшие практики проектирования SDK для Android-приложений.

Это, разумеется, не все сессии, другие тоже определённо заслуживают вашего внимания!

🫴 Итак, давайте разыграем проходку. Для участия в розыгрыше нужно оставить комментарий под этим постом и написать про самую интересную архитектурную задачу в вашей практике. Итоги розыгрыша подведём ровно через неделю, удачи!

А те, кто не хочет участовать в розыгрыше, ловите промокод на скидку для покупки билета на сайте: android_crew_14_8RuHEz
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3🥱31
Мой архитектурный факап

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

Адаптируя Decompose в одно из наших приложений, мне пришла в голову гениальная идея: раз Decompose позволяет разом менять весь стек экранов, то почему бы не сделать навигацию по стейту из бизнес-логики?

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

В чём проблема? Если мы сразу обработаем диплинк и перейдём на нужный экран, то он тут же перетрётся изменением глобального стейта после загрузки данных.

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

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

А о каких решениях в архитектуре пожалели вы?

#Navigation #Decompose
👍241
Как поменять ключ подписи приложения

Я удивился, что мало кто знает, и некоторые даже не верят, что возможно поменять сертификат для ключа подписи вашего приложения.

⚠️Работает это только для App Bundle, и в случае Google Play придётся использовать Google Play App Signing.

При этом не стоит путать ключ загрузки и ключ подписи: иногда это один и тот же ключ, но по умолчанию Google предлагает сгенерировать свой ключ подписи, а ключ загрузки нужен, чтобы идентифицировать, что сборка подписана вами. Отсюда следует, что поменять ключ загрузки вообще не проблема, так как итоговый APK всё равно будет подписан другим ключом.

Но как изменить ключ подписи? Ведь система просто не даст установить приложение с одним package id и разными ключами 🤔

На самом деле это возможно, начиная с Android N (API 24). Вы можете сделать это вручную с помощью apksigner, для этого вам потребуется доступ к старому и новому ключам:


apksigner sign --in ${INPUT_APK} \
--out ${OUTPUT_APK} \
--ks ${ORIGINAL_KEYSTORE} \
--ks-key-alias ${ORIGINAL_KEY_ALIAS} \
--next-signer --ks ${UPGRADED_KEYSTORE} \
--ks-key-alias ${UPGRADED_KEY_ALIAS} \
--lineage ${LINEAGE}


Но в случае обновления приложения в Google Play нужно делать это через консоль. Переходим по ссылке и запрашиваем обновление ключа подписи, для этого придётся загрузить приватную часть сертификата в консоль. Сделать это можно только раз в год.

Как это работает?

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

Когда может понадобиться?

🔘Если предыдущий ключ был скомпрометирован.
🔘Вы выбрали автоматическое подписание в Google Play, а теперь хотите сделать одну подпись приложения для всех сторов.
🔘Вы подписывали приложения разными ключами, но теперь хотите использовать один ключ для безопасного обмена данными между приложениями.

#GooglePlay #AppSigning
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥71
Как с пользой провести День программиста?

Конечно, посмотреть доклад моего коллеги Евгения Мельцайкина о том, как мы делали медиаленту, решали проблемы синхронизации контента и как нам во всём этом помог Decompose 🌳

Женя выступает на IT-фестивале KODE WAVES, доклад начнётся уже совсем скоро, в 11:30 МСК.

🔴 Ссылка на прямую трансляцию
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13
Manual DI

DI-фреймворки продолжают появляться как грибы после дождя. Теперь рекомендуют использовать Metro, но всё чаще можно услышать, что люди принципиально отказываются от каких-либо библиотек для реализации DI. Так как в моей команде мы в основном делаем переиспользуемые общие модули, мы тоже давно отказались от DI-фреймворков. И знаете что? Мы вообще не испытываем из-за этого каких-либо проблем.

Тут я вспомнил про свой KMP-сэмпл и решил, что будет круто показать всё это на примере и заменить Koin в проекте. Но хорошо, что я не начал делать это раньше времени: буквально на докладе про сравнение DI-фреймворков с Podlodka Android Crew я узнал, что Александр Власюк уже всё сделал раньше и даже заслал pull request 🌐

Примечательно, что Manual DI не только даёт compile-time safety по сравнению с Koin (без всяких плагинов), но даже количество строк кода в проекте сократилось 😲

Понятно, что это всего лишь пример. Если использовать Koin глобально, то кода с Manual DI придётся писать больше. Однако я придерживаюсь подхода, при котором DI должен быть изолирован внутри модуля, а зависимости должны быть объявлены явно, чтобы можно было легко переиспользовать этот модуль где угодно.

А вы что думаете, стоят ли DI-фреймворки, чтобы их изучать и постоянно мигрировать проект на все более новые решения

#DI #Kotlin #KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍21🔥6🗿3
Изменение конфигурации в прошлом

Еще пару лет назад я заметил, что если в AndroidManifest явно прописать все варианты изменения конфигурации в configChanges, то Compose сможет самостоятельно подхватить подавляющее большинство изменений без какого-либо дополнительного кода. Но тогда я был непонят сообществом, и никто это всерьез не воспринял 😨

Теперь же об этом заговорили инженеры из Google, рекомендую посмотреть доклад с Droidcon 🟥. Начиная с compileSdk 36, можно одной строчкой игнорировать все текущие и будущие причины пересоздания Activity из-за изменения конфигурации.

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

А вы что думаете, готовы ли вы забыть об изменении конфигурации в Android и о ViewModel в частности?

#Android #Compose
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29👎64🔥4😎3😁1
Проблема KSP

Kotlin Symbol Processing — современная технология для генерации кода, но насколько безопасно использовать библиотеки с KSP в проекте?

При обновлении зависимостей мы попали в следующую ловушку: не все библиотеки, которые мы используем, поддержали KSP2, и при этом новая версия Room крашится, если явно отключить поддержку KSP2 в gradle.properties. Сейчас ещё можно обойти проблему, понизив версии, но начиная с AGP 9 и Kotlin 2.3.0 KSP1 перестанет работать.

Что с этим делать?

🔘Можно включить режим ждуна и мониторить, когда авторы сторонних библиотек добавят поддержку, но не факт, что это произойдёт.
🔘Форкнуть библиотеку и реализовать поддержку самостоятельно, что может оказаться нетривиальной задачей, если раньше с KSP вы не работали.
🔘Избавиться от зависимости на такую библиотеку. Если она не глубоко интегрирована в проект, то проще выбрать этот путь, тогда при очередном обновлении зависимостей проблем не возникнет.

А используете ли вы в своих проектах библиотеки с KSP, кроме Room и Dagger?

#KSP #Android
Please open Telegram to view this post
VIEW IN TELEGRAM
👍211🤔1
Советы по работе с AI-агентами для начинающих

На днях посмотрел отличный доклад от Евгения Сатурова на Podlodka AI Crew о страхах разработчиков и типичных ошибках при работе с AI-агентами.

Я делал точно такие же ошибки, поэтому поделюсь советами с вами:

🔘 Выбирайте лучшую доступную модель на сегодня, не используйте auto-режим в Cursor и подобных инструментах.
🔘 Не пишите задачи напрямую. Формулируйте мета-промпт с описанием задачи для модели, чтобы она составила вам подробный таск-промпт.
🔘 В мета-промпте пишите, что вы хотите сделать, а не как, избегайте чрезмерной специфики.
🔘 Прикладывайте весь необходимый контекст. Плохо, когда модель начинает делать семантический поиск по проекту.
🔘 Не дробите задачу слишком сильно — это неэффективно. Современные модели могут достаточно долго работать автономно, главное не вылезти за контекст. По возможности используйте сабагентов.
🔘 Не вступайте в споры с моделью и не правьте код руками. Просто откажитесь от сгенерированного кода, обновите таск-промпт, правила проекта и попробуйте снова.

💬 Делитесь в комментариях своими лучшими практиками по работе с AI-агентами.

#AI
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍19🤡18😡21🥴1
Мы в команде создаём переиспользуемые общие модули между приложениями, и общая логика ключевых модулей шарится между Android и iOS. Это, безусловно, несёт в себе много плюсов, но и добавляет много сложностей.

Например, так сложилось, что в Android все модули находятся в монорепозитории, а в iOS каждый отдельный модуль — это отдельный репозиторий из-за особенностей менеджера пакетов Swift (SPM).

Поэтому мы предоставляем общий фреймворк через SPM, который iOS-разработчики могут подключить как отдельную зависимость.

И если вы шарите код только одной библиотеки, всё достаточно просто. Но когда появляется вторая и третья библиотека, начинаются проблемы. В KMP рекомендуется использовать так называемый umbrella-модуль, чтобы не тащить рантайм KMP в каждый отдельный фреймворк.

Но это несёт в себе одну большую проблему: всё, что мы экспортируем, попадает в одно пространство имён. Соответственно, одинаково названные классы при интеропе в Objective-C будут переименованы: к одному из классов добавится нижнее подчёркивание. И изменения в одном модуле легко могут сломать другой 🙃

Мы пока полноценно не решили эту проблему, но выработали правило: обязательно указывать имя модуля для всех публичных сущностей, которые экспортируются в Objective-C. Но с приходом Swift Export проблема должна отпасть, так как там можно будет указывать отдельный импорт для каждой библиотеки.

Это далеко не единственная проблема, с которой мы столкнулись. Если тема интересна — ставьте реакции, и я напишу ещё посты по теме.

#KMP #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👍775🔥3🤡3😎2👏1
Forwarded from Android Broadcast
‼️ ИЩУ КАНДИДАТА! Собеседование на Kotlin Multiplatform разработчика

Алексей Панов @kotlin_adept , опытный мобильный разработчик, реализующий приложения с применением KMP, проведет собеседование на позицию Kotlin Multiplatform разработчика в прямом эфире на YouTube канале "Android Broadcast" (время и дата будут объявлены позже)

Требования к кандидату:
👉 Опыт в мобильной разработки
👉 Опыт с Kotlin
👉 Понимание как происходит разработка приложений с KMP

Будет теория и практика. Это ваш шанс проявить себя и заявить на большую аудиторию о своих возможностях!

Если решили принять участие - заполняйте анкету!

#AndroidBroadcast
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👎2
Проблема версионирования

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

Мы разбиваем библиотеку на две части: core и compose. В core-модуле, соответственно, лежит вся логика, а в compose — только вёрстка. При этом каждый модуль мы делим на пакеты api/internal и с помощью правила detekt запрещаем использовать публичные сущности из пакета internal.

Также мы стараемся избегать использования сторонних библиотек, кроме ключевых, таких, как Ktor, SQLDelight, но в качестве исключения мы приняли решение использовать Decompose. Это позволяет значительно упростить интеграцию с общим кодом в iOS, ведь всё, что нужно сделать — это смаппить жизненный цикл. А дальше, в зависимости от текущего состояния навигации, показываем тот или иной экран и отправляем события в компонент. Это позволяет скрыть все детали реализации и меньше страдать из-за проблем с интеропом.

Однако то, что хорошо работает на iOS, создаёт проблемы на Android, так как в публичном интерфейсе core-модуля приходится раскрывать все интерфейсы компонентов, чтобы иметь возможность обращаться к ним из ui-модуля. Хотя для интеграции модуля в Android достаточно передать верхнеуровневый компонент из core-модуля в экран, никто не мешает разработчикам обращаться к другим публичным сущностям.
Одним из решений здесь видится использование специальных аннотаций, например @InternalVisibilityAPI, которые будут предупреждать пользователя о том, что это внутренний API библиотеки.

В такой парадигме поддерживать обратную совместимость API, а тем более ABI, почти нереально. Поэтому, поскольку это внутренние библиотеки, мы приняли решение поднимать мажорную версию только в том случае, если реально ломаем точки интеграции API. Для iOS мы просто создаём задачи на доработку, где указываем, что поменялось в этом релизе и что требует обновления.

Процесс получился далёким от идеала, но пока что это работает 🙃

#KMP #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👍282
🟥 Сегодня провожу публичное собеседование по Kotlin Multiplatform на YouTube-канале Android Broadcast в 19:00 мск.

Это уже мое четвертое публичное собеседование, в котором я стараюсь раскрыть основные аспекты работы с современными технологиями:

⏸️ Собеседование по Kotlin Coroutines
⚙️ Собеседование по Jetpack Compose
🤖 Собеседование мобильного разработчика

Сегодня на собеседовании будет задачка на ревью проекта с плохим кодом, но с упором на KMP. И по ходу эфира обсудим все нюансы интеграции общего кода с iOS.

Если вам интересна эта тема, обязательно приходите на прямой эфир, будет интересно! А в конце я смогу ответить на все ваши вопросы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥483🤡3
Материалы для углублённого изучения KMP

По мотивам вчерашнего собеса хочу посоветовать классные доклады, которые помогут вам глубже разобраться в принципах работы Kotlin Multiplatform и Kotlin Native, а также лучше понять нюансы интеропа со Swift-кодом.

На английском:

🔘ЖЦ объектов в Kotlin/Native
🔘Процесс компиляции в Kotlin/Native, отличия статических и динамических фреймворков
🔘Проблемы текущего интеропа и возможные пути улучшения
🔘Разница между Kotlin и Swift concurrency
🔘Принцип работы Swift Export

На русском:

🔘Совместная работа Kotlin/Native GC и ARC в Swift
🔘iOS Memory Management

#KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29🔥14😁1
Стоит ли переходить с Room на SQLDelight?

На данный момент обе библиотеки поддерживают KMP. Если раньше особого выбора не было, то теперь многие могут задаться вопросом: стоит ли вообще переходить с Room?

Я считаю, что нет, не стоит. Конечно, у каждой библиотеки есть свои преимущества и недостатки, но, на мой взгляд, у SQLDelight их заметно больше:

🔘 Нельзя задать разные имена для таблицы в БД и сгенерированного класса. Если вы придерживаетесь общепринятого синтаксиса именования таблиц, то имена сгенерированных классов будут выглядеть просто ужасно.
🔘 Видимость сгенерированных файлов также нельзя регулировать — все они будут public.
🔘 Нет поддержки suspend-функций, приходится явно менять диспетчер для каждого запроса. (оказывается есть, в настройках плагина есть свойство generateAsync)
🔘 Нельзя сразу сгенерировать класс с отношением many-to-many или другими связями, например, чтобы получить фильм со списком актёров, придётся делать дополнительный маппинг на стороне Kotlin.
🔘 Нет автоматических миграций, как в Room (но в целом это зло).
🔘 Очень скудная документация.

Из плюсов я бы выделил следующее:

🟢 Небольшие таблицы можно сразу смаппить в доменные типы с помощью Type Projections.
🟢 Нет магии аннотаций, все запросы пишутся явно.
🟢 Нет зависимости на KSP и плагины компилятора.
🟢 Поддерживается больше таргетов, чем в Room.
🟢 Может работать не только с SQLite.

В общем, я пришёл к выводу, что Room для меня выигрывает у SQLDelight, и мигрировать с него я бы не стал. Но и возвращаться обратно, если вы уже перешли, особого смысла тоже не вижу.

А что думаете вы, какая из библиотек вам ближе

#Room #SQLDelight #KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
25👍12❤‍🔥3
10 кругов ада, или как вручную перенести все фотки из-за аккаунта разработчика

Так вышло, что фотографирую я не очень часто, и только сейчас у меня закончилось место на Google Диске. Теперь в каждом своём приложении Google показывает страшные баннеры и вынуждает купить подписку 🤑

Что ж, убедили, идём покупать. Но с русским платёжным профилем ничего не купить. Зачем тогда предлагали? Ну да ладно.

Пытаемся поменять платёжный профиль, но этого сделать нельзя из-за активного аккаунта разработчика 🤨

Аккаунт я давно забросил и все приложения там удалил, но Google заодно «удалил» и мой аккаунт, так как я не подтвердил личность.

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

Тут я понял, что ситуация патовая и надо что-то делать. Одним из вариантов было создать новый аккаунт для фоток и заодно перенести все фото на Яндекс Диск.

Окей, качаем через Google Takeout архив со всеми фотками. Метаданные EXIF лежат там в отдельном JSON-файле, соответственно, ни данных о дате, ни геолокации в фотке нет, и нужно это как-то восстанавливать.

Я нашёл скрипт на Python, который это делает, и пришлось ещё немного подвайбкодить, чтобы всё заработало...

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

#Offtop
Please open Telegram to view this post
VIEW IN TELEGRAM
1🤯22😁83👍1😨1
Зоопарк кроссплатформенных фреймворков

Думаю, вы все слышали про такие фреймворки, как Flutter и Expo (React Native) для разработки кроссплатформенных мобильных приложений и не только. Но, разумеется, таких фреймворков существует значительно больше, и по сей день появляются новые решения.

Давайте рассмотрим некоторые из них:

Valdi — фреймворк от Snapchat, где UI пишется на TypeScript DSL, который напрямую компилируется в нативные вьюшки. Разработчики обещают производительность, сопоставимую с нативными приложениями, так как фреймворк не использует ни WebView, ни JavaScript Bridge. Поддерживает Android, iOS и macOS.

ArkUI-X — проект, расширяющий декларативный UI-фреймворк для разработки приложений под HarmonyOS NEXT и позволяющий добавить поддержку компиляции под Android и iOS. Это ещё один фреймворк, использующий TypeScript, а точнее его надмножество ArkTS.

Skip — единственный платный для корпоративного использования фреймворк, который изначально представлял собой транспилятор из Swift в Kotlin и позволял переводить нативные iOS-приложения на SwiftUI в Android-приложения с Jetpack Compose. Но в новом режиме Fuse Skip начал использовать недавно вышедший Swift SDK для Android, что позволит уйти от прямой транспиляции кода по крайней мере для бизнес-логики.

Если честно, я не верю в широкое распространение этих фреймворков, но будет интересно посмотреть, к чему всё это приведёт. А что думаете вы? Попробовали бы один из этих фреймворков для разработки мобильных приложений?

#Crossplatform #Frameworks
👍12😐7
Как бигтехи кошмарят вас на собеседованиях

Успешно пройти секцию по профильным хардам, но смачно опозориться на логической задаче с часами? В этом вся суть интервью в бигтехе

Автор этой истории побывал на собесе в ❤️ и рассказал всю правду о клоунаде, которая там происходила. Готовьте попкорн!

Вита Заебумба | Путь корпората — топовый канал про IT, сферу найма, трешовые собесы и работу в корпорациях. Просто кладезь кулстори не только от автора, но и от подписчиков

Атмосфера 12/10: авторская подача, юмор и угарные комменты от аудитории, состоящей из системных, дата аналитиков, разрабов, продактов и других айтишников

🔥Истории, которые уже успели стать бестселлером:

🟡Поймала интервьюеров за руку на собесе в известном маркетплейсе
🟡Я стала эйчаром и вот что выяснила. Правда о ситуации на рынке IT
🟡Эффект Писюхи, или как я столкнулась с эйджизмом в найме
🟡Афигеть не встать — какие мутные схемы заработка вам впаривают галеры
🟡Если твой руководитель ведет себя так, беги оттуда

Но тут не только про веселье и треш. Подписывайтесь, если хотите:

🟢Узнать лайфхаки продающего резюме
🟢Быть в курсе актуальной ситуации на рынке
🟢Обойти 90% кандидатов
🟢Не продешевить на собесе и выгодно себя продать

➡️ @vitazaebymba

Реклама. Малютина В.А. ИНН: 502743782203 Erid: 2Vtzqwnsijq
Please open Telegram to view this post
VIEW IN TELEGRAM
💊11🤣5👎31👍1
Как улучшить дальность сканирования кодов маркировки

Библиотеки вроде Google ML Kit, ZXing или его аналога на C++ со стандартными настройками камеры имеют довольно посредственную дальность сканирования, приходится подносить камеру очень близко, чтобы хоть что-то отсканировать. Особенно это касается акцизных марок нового образца. При этом, если взглянуть на коммерческие решения, они работают на голову выше.

Как можно улучшить ситуацию?

🟢Как ни странно, можно попробовать уменьшить разрешение камеры, двух мегапикселей более чем достаточно для распознавания.
🟢Увеличить параметр zoomRatio в камере по-умолчанию, например, установить 1.5f вместо 1f.
🟢Реализовать автоматический зум к потенциальным кодам. Для этого в ML Kit появились настройки enableAllPotentialBarcodes и ZoomSuggestionOptions.
🟢Ограничить размер зоны сканирования.

Наверняка можно придумать что-то ещё. Хотелось бы спросить совета у тех, кто уже сталкивался с подобной задачей, есть идеи, что еще можно сделать?

P.S. Обучение собственной модели не предлагать 🙂

#Camera #BarcodeReader
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21👍5❤‍🔥3😈1
Посмотрите на код на изображении. Эта composable-функция используется на экране с камерой, чтобы сделать полупрозрачную рамку по периметру. Как думаете, в чем тут проблема?

Вместо прозрачного выреза на некоторых старых устройствах будет чёрный прямоугольник.

Я уже когда-то сталкивался с этой проблемой, когда Compose еще не было и в помине. При работе с Android Canvas проблема заключалась в использовании PorterDuff.Mode.CLEAR.

В прошлый раз эту проблему в AndroidView удалось пофиксить, переведя отрисовку на hardware-accelerated layer:


setLayerType(LAYER_TYPE_HARDWARE, null)


Но как сделать то же самое в Compose? Если просто получить текущий View через LocalView, то, вероятно, мы не получим нужного поведения, так как изменим layerType для верхнеуровневой вьюшки.

Мне ничего лучше не пришло в голову, чем сделать composable-функцию враппер, в которой контент будет прокидываться в AbstractComposeView, где уже и будет происходить изменение layerType.

Таким образом, чтобы пофиксить проблему, достаточно будет обернуть код на изображении в этот враппер. Если нужен код враппера, напишите в комментариях.

P.S. Как думаете, когда люди уже перестанут использовать семилетние смартфоны Xiaomi?

#Android #Canvas #Compose
🤯22🔥3😭3👍2
🔥 Уже понимаете, что Kotlin — это будущее автоматизации? Тогда не пропустите наш вебинар

24 ноября в 20:00 мск! Роман Сперанский расскажет, почему Kotlin — это ключ к быстрым, чистым и умным тестам, а также поделится практическими советами для вашего развития.

Регистрируйтесь по ссылке 🔗

Хотите перейти к реальной практике и освоить автоматизацию на Kotlin?

Начинайте обучение сейчас и получите 5% скидку!

Онлайн-курс включает 22 занятия, домашние задания, живые вебинары, 100 часов практики и два проекта для портфолио — всё под руководством эксперта с 16-летним опытом.

Узнайте все детали курса на сайте 🔗
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5👎4🤝1