Android Good Reads
3.87K subscribers
344 photos
13 videos
1 file
2K links
Самые интересные статьи, видео и новости, связанные с Android разработкой. Не больше трёх материалов в день.

Автор канала: @Lamprof

Размещение рекламы: @tanyasanovna
Download Telegram
System UI Compatibility and Immersive Status Bar

Разбираемся как в Compose обращаться с областью взаимодействия приложения

👉 enableEdgeToEdge() - растянуть область и забрать контроль у системы
👉 WindowInsets понять область отступа системных компонентов и вставить в padding вашего объекта
👉 Modifier.systemBarsPadding() или Modifier.safeDrawingPadding() сделать тоже самое, но с помощью модификатора
Посмотрите на этот кусочек кода. Выглядит странно, хотя точно используется вашим приложением. Ну а кто транзитивно не использует okio?

Именно с этого момента начинается статья об оптимизации подсчета количества символов в числе. Итоговые результаты такие:
Немного анонсов грядущих изменений в Kotlin. Вероятно, появится объединение типов и ошибок

Более подробно в тикете: kotl.in/f28fo8

Источник
Это не финальный вид, а только предположение о том, как может выглядеть реализация
Сравниваем 2 APK на уровне dex. Не маст-хев инструмент, но посмотреть на сколько хорошо работают ваши proguard правила и сверить apk от релиза к релизу может быть удобно.

Сам инструмент: https://github.com/theapache64/dex-diff
Про новые layout с Google I/O

Новые 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!

Гайд о том как дебажить дерево зависимостей проекта на предмет коллизий

👉 Базово построить дерево зависимостей можно, но скорее всего оно будет нечитаемым
./gradlew :app:dependencies > dependencyTree.txt


Добавив --scan, можно посмотреть на аккуратную версию в браузере

👉 Это же дерево зависимостей лучше всего отфильтровать по конфигурации с помощью --configuration. Они бывают: compileClasspath, runtimeClasspath, testCompileClasspath, и testRuntimeClasspath

👉 Найдя проблемную зависимость, разбираем ее с помощью dependencyInsight. Вы увидите как и почему выбирается та или иная версия для проекта.

А что дальше? В статье исключается транзитивная зависимость из одной из библиотек, тем самым решая изначальную проблему конфликта при обновлении фреймворка
Не успели мы перейти на Kotlin 2, как Kotlin 2.0.20-Beta1 приносит новые изменения. Функция 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/
This media is not supported in your browser
VIEW IN TELEGRAM
Спустя 4 года в беклоге, фича с заполнением обязательных параметров готова и будет доступна в IDEA 2024.2 EAP. До Android Studio докатится значительно позже.

Мне этого функционала очень давно не хватает
Сегодня разберем частый и не очевидный паттерн - 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 диспатчеры для задач связанных с записью данных
👉 Автор приходит к выводу что лучше использовать малое количество потоков, дробя большую задачу на подзадачи, для быстрого выполнения

Код, соответсвующий результатам на графике, приведен ниже. Автор так же делает сравнительный анализ для каждой операции, так что рекомендую глянуть статью целиком!



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. 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
123.gif
18.4 MB
Jetpack 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
This media is not supported in your browser
VIEW IN TELEGRAM
RemoteConfig на Гугл таблицах

В целом, гугл таблицы можно использовать как бекенд для вашего пет-проекта или если нужно быстро набросать POC. Еще 1 история успеха стартапа, который так и сделал - Levels.fyi

Под капотом ничего сложного - просто получение таблицы по ссылке и чтение данных из нее. Не безопасно, не поддерживаемо, но быстро и работает!
А как собеседоваться в 2023?

На этот раз менее техническая статья, больше про то как попасть на собеседования. Актуально для тех кто ищет работу в Европе/США. Статья стоит того чтоб ее прочитать целиком

👉 Просто оставить свое резюме на сайте компании больше почти не работает
👉 Найм сократился и большее предпочтение компании отдают рекомендациям. Ищите друзей и друзей-друзей и друзей-друзей-друзей в компанию куда вы хотите
👉 Ваше красивое 7 страничное резюме о том как вы делали свою работу в последние 10-15 лет скорее всего не прочитают. Когда на вакансию по 100+ заявок в день, выбирают того у кого понятно кто он и что он
👉 Системы, парсящие и оценивающие ваше резюме, не так умны, как кажется, так что лучше подстроиться под них. Проверить свое: resumeworded.com
👉 Как бы вам не нравилось оформлять LinkedIn - если через него вы ищете себе работу ИЛИ хотите чтоб работа там находила вас - это надо сделать
👉 Алгоритмические задачки/систем дизайн все еще неотъемлемая часть большинства собеседований - просто подготовьтесь. По-другому никак

По моему опыту - все так. Наибольшая конверсия при подаче через знакомого/существующий контакт в LinkedIn. Когда я подтюнил LinkedIn - мне начали писать рекрутеры с предложениями. Когда я подтюнил резюме - даже иногда стал пробиваться через холодные подачи на вакансию.
Улучшаем проигрывание видео через ExoPlayer

👉 В Reddit классически использовали DASH формат для Android и HLS для web/iOS. -> Заменили на mp4 для коротких видео длиной менее 45 секунд. Количество ошибок плейбека снизилось на 5%, просмотры за счет ускорения запуска увеличились на 1%
👉 Не стали использовать SimpleCache и стандартные методы хранения, а воспользовались DownloadManager. У этого метода есть и минусы. Например, подгрузить заранее первые 500kb данных из видео - нельзя
👉 Динамический размер буферизации для видео разной длины. Это сказалось на метриках, а вообще про буферизацию в реддит можно почитать тут
👉 Адаптивный битрейт через BandwidthMeter так же сказался на продуктовых метриках
👉 Для рендера использовали TextureView, но планируют перезжать на SurfaceView, который лучше работает с GPU, но может сказаться на перфомансе и потреблении батарейки

И что?
Проводите A/B тесты не только продуктовых фичей, но и платформенных чтобы понимать куда двигаться дальше. Связывайте продуктовые и платформенные метрики. ExoPlayer предоставляет неплохой интерфейс AnalyticsListener чтобы собирать данные касательно плеера - не самый удобный, но лучше чем ничего