TGViewer
Channel Public Channel
Android Good Reads

Android Good Reads

@droidgr

Самые интересные статьи, видео и новости, связанные с Android разработкой. Не больше трёх материалов в день.

Размещение рекламы: @tanyasanovna
Subscribers
4.02K
Photos
420
Videos
17
Links
2.2K

Showing posts older than #2142 · Back to latest

Older Posts 20 shown
Post #2141 3.06K
Обновляем приложение через Github Releases без маркета

Все достаточно очевидно:
👉 Выкладываем приложение на GitHub как последний релиз
👉 Через api GitHub'а тянем последнюю версию и информацию о ней
👉 Вытягиваем из артефактов релиза apk
👉 Запрашиваем установку пакета у пользователя

Для публичных релизов необходимо, чтобы ваш проект был опенсорсным + весь флоу немного портит пользовательский опыт. Откат от app bundle к apk файлу тоже выглядит грустно
Из плюсов, если вы используете гитхаб, то этот способ отлично встроится в ваш релизный процесс и моментально раскатит приложение на ваших пользователей, избегая длительного процесса код-ревью.
  • 🔥 6
  • 🥴 2
Post #2140 3.14K
Интересный сравнительный анализ кроссплатформы и нативной разработки у Никиты Куликова(@localhost_ru) . Понятно откуда берется использование излишних ресурсов, но для некоторых продуктов это реальный повод задуматься над резонностью использования Flutter/CMP
Telegram Локалхост (Никита Куликов) Почему кроссплатформа это плохое решение? 1) На скринах выше - одно и то же приложение, написанное нативно и с использованием кроссплатформы. "Экономия" на разработчиках приводит к ухудшению пользовательского опыта 2) Кроссплатформенное приложение писать…
  • 👎 9
  • 🔥 4
  • 🥱 4
  • 👍 2
Post #2139 3.38K
Ну штош...

Варианты организации мультимодульной архитектуры

1️⃣ Каждая фиче-директория содержит 2 сабмодуля: domain и presentation, разделяя эти слои физически.
Это сильно усложняет проект, но дает масштабируемость на больших проектах

2️⃣ Один общий модуль features для всех фичей приложения.
Сильно упрощает проект, но если это небольшое приложение, то поможет в выделении всей бизнес-логики в отдельный модуль. Я, честно говоря, не вижу никаких преимуществ в таком подходе

3️⃣ Превращаем фиче-деректорию из п.1 в фиче-модуль с двумя сабмодулями domain и presentation.
Бенефиты в виде дополнительного модуля на каждую фичу могут повлиять на скорость сборки, но дадут удобство в способе подключения модулей

4️⃣ Отдельный модуль для каждой фичи, и все это лежит в папке features
Наверно это самый базовый способ вкатиться проекту в мультимодульную архитектуру, физически разделяя компоненты в приложении

Как и, главное, почему именно так, вы организовали разделение на модули в своем приложении?
Medium Approaches for Multi-Module Feature Architecture on Android Designing an effective architecture for your Android project is crucial, especially when you aim to maintain it long-term. The strategy you…
  • 🔥 4
  • 🥱 3
  • 👍 1
  • 👌 1
Post #2138 2.95K
Если вы теряетесь в ответе на вопрос "Почему нужно использовать тут class, а не data class", то эта статья для вас. Конечно, документацию тоже нужно глянуть

👉 Как работает data class под капотом
👉 Какие есть ограничения
👉 Какой синтаксический сахар предлагает

Бонус
Посмотреть на то как выглядит голый код вашего датакласса, возможно так понятнее, зайдя в Tools -> Kotlin -> Show Kotlin Bytecode и кликнуть Decompile
  • 🔥 4
  • 👍 3
  • 😁 2
  • 😱 1
Post #2137 3.53K
Со сложных архитектурных задач прошлой недели обратимся к популярным ошибкам в Jetpack Compose:

👉 Забываете использовать remember, или используете его когда не надо, как тут
👉 Постоянно используете Modifier.fillMaxSize() без надобности
👉 Игнорируете оптимизации производительности. Делаете тяжелые операции при каждой рекомпозиции
👉 Путаете State и MutableState. Почитать отличия можно тут
👉 Не знаете как устроены LaunchedEffect и DisposableEffect. Почитать тут, а в самой статье неплохие примеры про неверный key, лишние рекомпозиции и ошибки жизненного цикла
👉 Создаете сложные и неподдерживаемые Composable с глубокой вложенностью
👉 Не используете тему и и цвета из нее, а применяете значения напрямую
👉 Забываете тестировать Composable. Для этого, кстати, не обязательно проходиться тест кейсами по пути до элемента, достаточно вызвать его отдельно и потыкать. Способы найти элемент внутри Composable описаны тут
👉 Игнорируете contentDescription. Доступность вашего приложения для людей с ограниченными возможностями очень важна! Не пренебрегайте этим, пожалуйста. О том как проверить свое приложение был пост тут

Внутри статьи есть примеры ошибок и правильной версии по мнению автора.
  • 👍 11
  • ❤ 3
  • 🔥 1
Post #2136 3.38K
Android Good Reads Замените UseCase на Интерфейсы Нашел невероятно красивое решение, как слой usecase, являющихся прокси к репозиторию, облегчить. Допустим у нас есть репозиторий: class CounterRepository { private val _value = StateFlow(0) val value: Flow<Int> = _value…
Немного контекста к посту выше.

Подразумевалось избавление от сценариев, когда у вас UseCase выглядит вот так:


class GetTaskListUseCase(
private val taskRepository: TaskRepository,
) {
operator fun invoke(): List<TaskItem> {
return taskRepository.getTaskItems()
}
}


Убирая этот UseCase вам придется обращаться к репозиторию напрямую из ViewModel, что позволит вызывать и другие функции репозитория напрямую

Крутая дискуссия случилась в комментариях с разными точками зрения, спасибо!
  • 👎 29
  • 👍 7
Post #2134 3.59K
Замените UseCase на Интерфейсы

Нашел невероятно красивое решение, как слой usecase, являющихся прокси к репозиторию, облегчить.

Допустим у нас есть репозиторий:

class CounterRepository {
private val _value = StateFlow(0)
val value: Flow<Int> = _value

fun addOne() { _value.update { it + 1 } }
fun subOne() { _value.update { it - 1 } }
}


Тогда примитивные прокси usecase(представим их сразу как интерфейсы) будут выглядеть так:

interface AddUseCase { fun addOne() }

interface SubUseCase { fun subOne() }

interface GetValueUseCase {
val value: Flow<Int>
}


Значит, в целом, мы можем представить репозиторий, как реализацию этих интерфейсов:

class CounterRepository:
AddUseCase,
SubUseCase,
GetValueUseCase {
override val value: Flow<Int> ...

override fun addOne() ...
override fun subOne() ...
}


А раз есть реализация, значит можно инжектить ее напрямую в VM

class CountingViewModel(
private val addOne: AddOneUseCase,
private val subOne: SubUseCase,
private val getValue: GetValueUseCase,
): ViewModel() {
...
}


Пример целиком, но с большим количеством обслуживающего кода: Гист

Вроде бы использованы базовые паттерны, но такой реализации еще не видел
  • 👎 75
  • 🤣 11
  • 👍 9
  • 🔥 5
  • 🤯 5
  • 🌚 2
  • ❤ 1
Post #2133 2.84K
Крутая находка: ksp форк anvil, фреймворка для помощи в инъекции зависимостей с Dagger 2

Зачем это было сделано?
Оригинальный фреймворк до сих пор на Kotlin 1.*, только на kapt и содержит проблемы с инкрементальной компиляцией. Форк умеет работать и с kapt и с ksp одновременно, а автор планирует продолжать его поддержку

KSP fork: https://github.com/zacsweers/anvil
Оригинал, для тех кто не знаком (1300+ ⭐️) : https://github.com/square/anvil
  • 👍 4
  • 🔥 2
  • 🤯 1
Post #2132 3.05K
  • 🙈 14
Post #2131 3.13K
Квиз!

В Composable, в большинстве случаев, если мы используем mutableStateOf(), мы фиксируем его состояние через remember(), чтобы сохранить его при рекомпозициях. Но если мы используем mutableStateOf() в Activity — нужно ли нам использовать remember()?

Пример кода:
class MainActivity : ComponentActivity() {

private var text = mutableStateOf("Hello!")

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AppTheme {
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
TextField(value = text.value, onValueChange = {
text.value = it
})

Text(text = text.value)
}
}
}
}
}


Ответ: клик
  • 🔥 4
  • 👍 3
Post #2129 3.2K
MutableState vs MutableStateFlow

👉 Область применения
MutableState используется в основном совместно с Jetpack Compose обобщая состояние
MutableStateFlow можно использовать на любом уровне абстракции в том числе на слое данных

👉 Потоки
MutableStateFlow потокобезопасен в отличии от MutableState у которого возникают сложности при объединении с фоновыми процессами

👉 Жизненный цикл
MutableState тесно связан с жизненным циклом Compose и гарантирует что не возникнет проблем на UI
MutableStateFlow больше привязан viewModelScope и подойдет для асинхронной работы с данными

В целом, это абсолютно разные вещи, несмотря на схожесть в нейминге. Не путайте State и StateFlow ❗️
Medium MutableState or MutableStateFlow: A Perspective on what to use in Jetpack Compose MutableState or MutableStateFlow: A Perspective on what to use in Jetpack Compose When building applications with Jetpack Compose, developers face a pivotal choice: should they use MutableState or …
  • 🔥 5
  • 🥰 4
  • 😁 4
  • ❤ 1
  • 👏 1
Post #2128 3.37K
Тем временем команда Android Studio выпустила Ladybug Canary 5 🐞, а недавний Feature Drop перешел в стадию релиз-кандидата

Что это значит для вас?
👉 Те кто сидит на Preview версии получил обновление IDE до 2024.2 + небольшие исправления существующего функционала. KMM плагин, как обычно, появится ближе к бете
👉 Для тех кто предпочитает стабильность, Koala получает финальные исправления и ждет вас с новым терминалом в стадии RC
  • 👍 5
  • 😁 2
  • 💯 2
Post #2127 3.81K
Android Good Reads 🗿 Полезности по защите кодовой базы. Чтобы скрыть часть своего проекта от Gemini LLM, которая присутствует в последних версиях Android Studio - добавьте .aiexclude файл по аналогии с .gitignore в корень проекта и укажите директории или конкретные файлы. Документация:…
Как Google поможет найти уязвимости в вашем коде

В ходе проверки линтером выявляются известные уязвимости и выводятся рекомендации по их исправлению со ссылкой на источник. Это полезно, потому что держать в голове весь OWASP в области мобильной разработки (https://mas.owasp.org/MASVS/) попросту невозможно. Работает начиная с AS Giraffe+
  • 👍 5
  • 🔥 3
  • 💯 1
Post #2126 3.7K
Google Workspace переносит свои продукты на KMP

Прошедший KotlinConf24 принес еще одну новость. Команда Google Workspace, а это такие приложения как Gmail, Docs, Meet, Calendar переводит свои продукты на KMP. Первым будет приложение Google Docs.

И это очень крутая поддержка для KMP и расширение комьюнити.
  • 👍 21
  • 🔥 8
  • 👎 2
Post #2125 4.36K
Цикл статей про архитектуру от Zsolt.

👉 Вводная часть про инструменты и что нас ждет в следующих частях
👉 Про обработку ошибок и Монады. Читаем про то что такое монады, как это связано с архитектурой Android и на какому слое приложить
👉 Mapping Зачем это делать и почему нельзя использовать 1 серверную модель на всех слоях. Нужно ли тестировать этот процесс, и как именовать функции чтобы не запутаться
👉 Response vs Reply классы Отличия и когда-какие используем. Организация нетворк слоя

Это не гайд для архитекторов, а скорее для мидлов, которым нужно начать углубляться в детали организации слоя данных
  • 👍 7
  • 🆒 3
  • 🔥 2
Post #2123 2.77K
🗿 Полезности по защите кодовой базы. Чтобы скрыть часть своего проекта от Gemini LLM, которая присутствует в последних версиях Android Studio - добавьте .aiexclude файл по аналогии с .gitignore в корень проекта и укажите директории или конкретные файлы.

Документация: https://developer.android.com/studio/preview/gemini/aiexclude
  • 👍 7
  • 🔥 2
  • 😁 2
Post #2122 3.26K
Как под капотом работает @Preview?

👉 Для просмотра метода с @Preview аннотацией используется androidx.compose.ui.tooling.PreviewActivity, который собирает параметры из @PreviewParameter и свойства из @Preview
👉 Все это должно как то собираться воедино, да? Это происходит во время градловской команды androidTest. На выходе получаем apk с превьюшками, который выводится в Android Studio.
👉 Как можно этим воспользоваться? Например, положить AndroidManifest.xml в module/src/androidTest и поменять параметры приложения, которое запускается для preview. А значит, мы можем и сами собрать приложение из наших @Preview и любых @Composable элементов на девайс!

В статье больше технических примеров, рекомендую глянуть. Практического применения этим знаниям я не могу найти, поправьте меня в комментариях если у вас есть идеи, но знать как работает под капотом инструмент, которым ты пользуешься всегда полезно
Medium Jetpack Compose Previews: Delving Deep Into Their Inner Workings Uncover the secrets of Jetpack Compose Previews! Learn to run them with adb, how to compile them and the nuances in multi-module setups.
  • 👍 7
  • 🔥 6
  • ❤ 3
  • 🤔 1
  • 😢 1
Post #2121 3.38K
Android Good Reads Какой DI фреймворк используете?
А вот вам еще 1 DI фреймворк, который никто не упомянул ранее!

Используем kotlin-inject в Kotlin/Compose Multiplatform проекте

Не рекомендация к использованию, а расширения кругозора ради: kotlin-inject (1200+ ⭐️)
Сompile-time инъекция зависимостей, не переусложненная схема использования и поддержка multiplatform (по сути, единственная альтернатива koin)
John O'Reilly Using kotlin-inject in a Kotlin/Compose Multiplatform project I’ve been using Koin in most of the Kotlin Multiplatform (KMP) samples I have but thought it would be good to include use of at least one other DI framework and this article outlines changes made to add kotlin-inject to the BikeShare KMP sample. This project…
  • ❤ 4
  • 👍 3
  • 💯 1
Post #2119 2.9K
Добавляем проверку на номер задачки в TODO через линтер

Пустые TODO маловероятно будут исправлены, если не имеют за собой закрепленной задачи. А имея задачу очень просто найти место где возникла проблема. Автоматизация проверки формата TODO через lint и как ее делать: тут и тут
  • 👍 6
  • 😁 6
  • 💯 1
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →