Telegram Web
​​Миграция с LiveData на StateFlow
#livedata #flow #jetpack

LiveData — классный инструмент, который позволяет получать данные не думая о жизненном цикле компонента. Он удобен, но есть недостатки:

🔹разработчики используют его повсюду, в том числе и в репозиториях, где его главная функциональность не нужна. Кроме того, репозиторий должен знать о минимальном количестве компонентов Android, а в лучшем случае вообще не знать;
🔹есть методы setValue() и postValue(), которые используются в зависимости от потока. И вам постоянно нужно помнить об этой разнице, когда вы делаете их вызов. В случае вызова setValue() не из UI-потока, вы получить Exception, а использование postValue() по всех случаях грозит проблемами. Отлично рассказали о разнице между этими методами тут.
🔹дополнительная зависимость в приложении. Меньшая из проблем, однако это лишняя библиотека, которую вам нужно затянуть в приложение.
🔹нет поддержки KMM.

Классной альтернативой является использование StateFlow. Он потокобезопасный, поддерживает KMM и не требует добавления новых зависимостей в проект.

Я уже начал мигрировать свой текущий проект на StateFlow и отмечу пару недостатков:

🔸нет привязки к жизненному циклу по умолчанию. Необходимо использовать методы типа lifecycleScope.launchWhenResumed() для обеспечания привязки.
🔸важно указывать значение при инициализации в отличии от LiveData. Решение для меня: если такого значения нет — указать null, а при подписке сделать фильтрацию на «не null». Просто один лишний оператор filterNotNull().

В остальном — шикарное решение, которое работает из коробки. Детальный гад по миграции и особенностям можно найти тут.

А вы уже переехали на Flow? Есть ли какие-то недостатки?
​​Ребят, а ведь сегодня 23 февраля — День защитника Отечества, ну и в этот день принято поздравлять всех мужчин и дарить им подарки.

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

Ну а в войну давайте играть только на Playstation, Xbox или ПК.

А давайте глянем, кто за что топит?
​​Annousing TheAndroidShow: Jetpack Compose
#compose #conference

Совсем недавно мы с вами смотрели за появлением alpha-версией Jetpack Compose, а между тем прошло 12 alpha-релизов и сегодня Google планирует анонсировать первую beta-версию!

Это шикарная новость, и даже организовано специальное мероприятие. Оно будет уже сегодня, 24 февраля в 20:00 по МСК. Ссылка с анонсом мероприятия тут. Надеемся, что на нём нам скажут дату релиза стабильной версии.

Кстати, есть классный канал, который посвящён полностью Jetpack Compose, рекомендую подписаться, чтобы не пропустить новостей, связанных с этим фреймворком. Кстати, с автором канала мы делали стрим, который может стать хорошим стартом в Compose 😉.
​​Android Scopes с Koin
#kotlin #koin #новичкам

Работа с жизненным циклом компонентов в Android может показаться достаточно сложной для новичков. Если дело касается работой с библиотеками для DI и Service Locator, то у многих появляется вопрос: как правильно управлять жизненным циклом компонентов?

Есть хорошая статья, которая расскажет о том, что такое Scope в Koin, и как правильно им управлять. Статья детальнее расскажет о встроенных в Koin скоупах, а также как сделать свой кастомный Scope.
Кстати, у Koin изменился дизайн сайта и, в целом, обновилась документация, а на носу выход свежих версий 3.0.1 и 2.3.0.
👍1
​​Выбор архитектуры для Jetpack Compose
#architecture #compose

Недавно Jetpack Compose перешёл в стадию beta, и ещё больше разработчиков подумывают о том, чтобы использовать его в своих текущих проектах. Но проблема заключается в том, что в уже существующую архитектуру может быть не просто интегрировать Compose.

Помочь в интеграции может эта статья. Автор сравнивает MPV, MVVM и MVI для использования с Jetpack Compose. Есть пример кода, где описывается логика проекта и то, как взаимодействуют слои. ✌🏻

Автор пришёл к выводу, что если в проекте есть MVVM и MVI, то интергрироваться с Jetpack Compose будет не так уж и сложно.
Мне кажется, что всё же идеальной архитектурой для Compose будет MVI.

Ссылка на исходный код проекта тут.
Тут неплохой канал с мемами для разработчиков подсказали — @java_memes.

Если хочется полистать ленту и почитать смешные мемы из IT, то вам сюда. Тут и про код, и про вакансии, и про текущие технологии, и про Яндекс со Сбером.

В общем, подписывайтесь — @java_memes.
​​Ещё больше про миграцию на Jetpack Compose
#architecture #compose

В предыдущей статье мы уже рассмотрели сравнение различных типов архитектур, а сегодня попалась ещё одна статья про использование Jetpack Compose в существующих проектах.

Автор в первой части рассказывает про Unidirectional Data Flow и про то, как применить его в проекте. По сути, это уже MVI паттерн для архитектуры, и можно посмотреть на пример его использования в простом проекте.

Вторая же часть уже связана непосредственно с имплментацией фичи. Это простой экран, который отображает список данных на экране. Автор показывает, как переходить от стандартного подхода в Compose-подход. Не уверен, что обязательно нужно делать столько слоёв, но в качестве примера подобный подход обязательно стоит рассмотреть.
​​Сравнение ArrayMap, SparceArray и HashMap
#theory

В Android SDK есть большой пласт коллекций, которые мы не используем: ArrayMap, SparseArray, ArraySet и т.д. Но все они дают определённые преимущества в сравнении с их более популярными «братьями».
И знание того, когда какую коллекцию использовать даёт преимущество при оптимизации приложения, а также при прохождении некоторых этапов собеседования.

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

Далее автор сравнивает эти три коллекции между собой, с точки зрения памяти и скорости доступа. Выводы:
▪️если у вас меньше 1000 элементов, то используйте ArrayMap, так как идёт выигрыш по памяти;
▪️если ключами является целое число, то используйте SparseArray, так как идёт ещё больший выигрыш по памяти;
▪️если значений больше 1000, то HashMap выигрывает по скорости;

Добавлю, что плюсом у HashMap является отсутствие привязки к Android SDK, что позволяет использовать её также и в KMM проектах.
Очень интересно изучать то, как работают коллекции изнутри и разбираться в привычных инструментах. 🔥
​​А сегодня у нас 8 марта — Международный женский день.

Поздравляю всех подписчиков женского пола с этим праздником, желаю тёплой весны, много цветов и любви.

Ну а парни — не забудьте поздравить ваших мам, жён и девушек с этим праздником, пусть улыбнутся.

А давайте тоже проголосуем, что лучше для подарка?
​​Практики работы с Coroutines
#coroutines

На сайте для разработчиков от Google появились практики работы с Coroutines. Давайте их рассмотрим.

🔹нельзя хардкодить Dispatchers. Особенно это касается работы с Coroutines во ViewModel. Google предлагает инжектить каждый диспетчер в отдельности и применять его в зависимости от контекста. Плюсом данного подхода является простота тестирования.
Из практики добавлю сюда передачу не конкретного элемента, а обёртки с 3 основными Dispatchers, которую можно переопределить для тестирования. На мой взгляд, такой подход удобнее.

🔹suspend-функции должны быть безопасными для вызова из основного потока. Предлагается использовать для этого withContext, где надо явно указать поток для выполнения функции. Хороший подход, но я не часто встречал его на практике.

🔹ViewModel должны быть ответственными за Coroutines. Довольно логичный паттерн: нельзя возвращать suspend-функцию во View, где запускать эту функцию и получать из неё какой-то результат. Правильнее будет использовать для этих целей Flow или LiveData.

🔹не делайте видимыми изменяемые типы из ViewModel, такие как MutableStateFlow или MutableLiveData. Это делается для того, чтобы избежать возможности отправки каких-то данных из View.

🔹слои бизнес-логики и данных должны возвращать или suspend-функции, или Flow. Плюсую за эту рекомендацию, потому что разработчики часто протаскивают LiveData во все слои приложения, где её фичи вообще не используются.

🔹избегайте GlobalScope. Это затрудняет тестирование и debug приложения. Если вам нужно «пережить» текущий экран, то стоит задуматься о scope, который будет управляться приложением или другим копонентом, живущим дольше, чем текущий экран.

🔹не забывайте про исключения. Обязательно стоит помнить о неуспешной работе suspend-функций и использовать для этого try-catch, хотя мне больше нравится CoroutineExceptionHandler.
​​Material Navigation Rail
#view #material

Возможно вы, как и я, пропустили выход свежей alpha-версии material-библиотеки. Туда включили фиксы, связанные с ProgressIndicator, а что нас больше интересует — так это новый компонент NavigationRail.

По сути, он повторяет функциональность BottomNavigationView, но располагается сбоку, а не снизу. Количество элементов при этом может быть от 3 до 7, а каждый компонент может включать в себя иконку, заголовок и значок-индикатор. Этот значок можно просто показать в виде точки, а можно добавить счётчик. Кроме этого, можно добавить header.

Как по мне, это хороший компонент, который раньше можно было реализовать при помощи RecyclerView.
Особенно компонент будет полезен приложениям, которые работают на планшетах. Чуть подробнее можно почитать о нём тут.
​​Будущее разработки: Kotlin Multiplatform и декларативный UI
#theory #crossplatform

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

Автор рассказывает о применении Kotlin Multiplatform на Android, iOS и Web. Основные тезисы:
🔹переиспользовать 85% кода;
🔹UI описывается при помощи декларативных фреимворков;
🔹MVI-архитектура с единым состоянием View;
🔹так как не нужно писать логику на 3 платформах, то клиентные приложения становятся дешевле в создании и поддержке.

Кроме того, автор описывает те решения, что существуют сейчас на каждой из платформ. Например, для декларативного UI на Android уже есть всем нам знакомый Jetpack Compose, для iOS — SwiftUI, а для Web — React.js.
Удивился тому, сколько уже написано решений для Multiplatform. Это и HTTP-клиент, и SQL-обёртка для базы данных, и аналог SharedPreferences. В общем, обо всём этом можно узнать, прочитав статью.

Она состоит из 3 частей, ссылка на первую, вторую и третью части.

Близко ли вам мнение, описанное автором статьи? И куда по вашему мнению движется разработка будущего?
​​Flutter vs Kotlin Multiplatform Mobile
#youtube

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

Если вы сторонник первого мнения, то может возникнуть вопрос, какой инструмент выбрать. В современном мире мобильной разработки есть два основных кроссплатформенных фреймворка: Flutter и Kotlin Multiplatform Mobile.

Давайте обсудим с экспертами в этих технологиях то, какие преимущества и недостатки имеет каждый фреймворк! Будем сравнивать и лёгкость в изучении, и размер приложений, и наличие библиотек, и коммьюнити… и многое другое. Свои идеи и вопросы можете накидать сюда.

Наши эксперты:
🔴 Александр Денисов, Lead Software Engineer, Co-Head of Flutter Competency в EPAM Systems, Flutter and Dart GDE. В разработке уже 15 лет, а с появлением Flutter активно увлекся разработкой на Dart.

🟢Артём Олков, разработчик в Яндекс.Диск, член ПК Podlodka iOS Crew. В программировании с 2011 года, с 2013 пишет на iOS. С 2019-го года разрабатывает Яндекс.Диск, где и внедрил KMM в прод.

Трансляция пройдёт онлайн, 24 марта в 18:00 по МСК, как всегда на Youtube-канале AndroidLive. Ссылка на трансляцию тут, задавайте свои вопросы и темы для сравнения тут.

До встречи!🤟
​​Как data-классы влияют на размер приложения
#kotlin

В Kotlin используется огромное количество разнообразных фич: null safety, smart casts, inline-функции, sealed-классы. Одной из самых часто используемых фич является data-классы.
Мы уже обсуждали на канале то, что разработчики используют их там, где вся функциональность этих классов не нужна. Хотелось бы ещё раз посмотреть на реальную цену использования data-классов с точки зрения размерности приложения.

При помощи R8 из релизного приложения удаляются componentN()-функции и метод copy(). Но имплементация toString(), equals() и hashCode() остаётся в проекте.

Автор статьи при помощи gradle-плагина удалил эти методы и получил уменьшение размера приложения на 500KiB (или 4% от всего размера приложения), а также уменьшение числа методов почти на 15000.

Можно попробовать применить этот плагин к своим приложениям, а также помнить о разумном применении data-классов.
​​Создание простого плагина в Android Studio
#theory

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

По сути, вся работа заключается в следующем:
1) Создаём новый проект, выбирая «IntelliJ platform plugin» из списка.
2) Далее создаём новое действие, наследуясь от класса AnAction.

В целом, это всё🤟. Осталось только подключить итоговый плагин к студии и выполнять нужные вам действия. Статья будет полезной, если вы планируете писать собственные плагины и автоматизировать рутинные действия.
​​Устанавливаем одновременно несколько версий приложения
#beginners

Многие разработчики используют свои телефоны в качестве устройств для тестирования и разработки. В целом, в этом нет ничего плохого, однако есть одна проблема: по умолчанию вы можете иметь только одну версию приложения на устройстве.
Ситуация усугубляется, если вы хотите держать одновременно debug, test и release версии.

К счастью, есть достаточно простое решение, которое позволит иметь сколько угодно версий одного и того же приложения на одном устройстве. Вот вам инструкция, как это сделать:
🔸настройте отдельные buildTypes. Сделаем test и release;
🔸добавьте applicationIdSuffix для test-версии. Например, _test;
🔸добавьте новое название test-сборки. В Android Studio добавьте новый xml-файл для строк, который поместите в папку test/res/values. Там уже сделайте нужное вам название, а название релизного билда переместите в release/res/values.
🔸добавьте новую иконку по такому же алгоритму. Вам нужно добавить её в test/res, Android Studio может всё переместить за вас.
🔸зарегистрируйте новое приложение в проекте для Firebase и поправьте файл google-services.json, который вам обновит сам Firebase.

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

В этом году начался ежегодный, пятый опрос про отечественные мобильные команды разработки. Из него можно узнать:
📖 откуда мобильщики получают новые знания;
💪 какие команды мобильной разработки самые сильные;
🌟 в каких компаниях мобильные разработчики хотят работать больше всего.

Вот результаты прошлого года, а поучаствовать в опросе этого года можно тут. Опрос займёт не больше минуты.

Не забудьте выбрать на одном из шагов также канал Android Live, для меня это очень важно 🤝.
​​Как измерить и оптимизировать размера Bitmap
#view #library

Если мы видим падение с OutOfMemory, то чаще всего думаем про утечки, которые есть в приложении. Однако, подобная ошибка не всегда вызвана утечками памяти. Одной из причин может быть чрезмерное использование памяти нашим приложением, из-за неправильной загрузки изображений.

Есть хорошая статья о том, как понять, что что-то не так с изображениями.

1️⃣ Первым шагом должно быть определение размера bitmap. Сделать это можно при помощи profiler. Автор также советует использовать устройства с Android 7.1 и ниже, так как там можно увидеть preview изображения.

2️⃣ Далее стоит посмотреть на качество вашего изображения и на размер ImageView, в который вы его загружаете. Если оно меньше, то полезно будет использовать методы fit() и centerInside() для Glide и Picasso.

3️⃣ Ну и напоследок стоит обратить внимание на профиль для загрузки изображений. По умолчанию может быть AGRB_8888, который использует 4 байта для каждого из пикселей. Но для большинства задач достаточно RGB_565, который использует в 2 раза меньше байтов. Да, качество изображений получается хуже, и нет поддержки прозрачности. Но для многих задач достаточно и такого качества.
​​onActivityCreated() во Fragment — deprecated
#fragment

Наверное, это уже не новость, но кто знает, может вы, как и я, пропустили её.
Стоило мне обновить версии библиотек в основном проекте, как я увидел, что метод onActivityCreated() стал deprecated.

Что это вообще за метод, и почему он стал теперь deprecated?
Этот метод существует по той причине, что фрагменты не могут существовать как независимый компонент. Для их работы и отображения необходим или контейнер в Activity, или родительский Fragment. Для того, чтобы сообщить, что Activity был создан и был создан этот метод.

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

Сейчас есть две рекомендации:
1️⃣ Все операции, связанные со View во Fragment нужно делать в onViewCreated().

2️⃣ Если вам нужно получить информацию о том, что Activity была создана, то можно зарегистрировать LifeCycleObserver в методе onAttach() и удалён после вызова метода onCreate(). Как по мне, звучит как костыль.

В целом, интересно, как будет вести себя Fragment дальше, если его делают менее зависимым от других частей приложения. 🤔
​​Дополнительная настройка Timber
#library

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

Есть вариант использовать официальную библиотеку от JakeWharton, но мне больше по душе fork, где добавили чуть больше возможностей для работы с Kotlin.

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

1️⃣ Добавьте глобальный тег в настройках, чтобы было проще увидеть логи из вашего приложения. Сделать это можно при помощи переопределения метода log в DebugTree, вызвав super.log(priority, "global_tag_$tag", message, t).

2️⃣ Добавьте название метода, из которого было показано данное сообщение. Для этого нужно переопределить метод createStackElementTag в том же DebugTree, отформатировав показ сообщения.
Кроме этого, можно добавить сюда же и номер линии из которой было вызвано сообщение.

Больше кода об этих настройках можно найти тут.
2025/08/29 19:22:03
Back to Top
HTML Embed Code: