TGTGInsighttelegram intelligenceLIVE / telegram public index
← Android Broadcast

TGINSIGHT SIMILAR POSTS

Trouver du contenu similaire

Chaîne source @android_broadcast · Post #8639 · 5 févr.

🤯Не нужно делать инжект всех зависимостей в конструктор Встретил код в проекте: class MyViewModel( ... private val sendDataUseCase: SendDataUseCase, ... ): ViewModel() { // Вызывается, когда пользователь в UI нажмёт на "Send" fun onSendClicked(...) { viewModelScope.launch { sendDataUseCase.invoke(...) // либо sendDataUseCase(...) } } } sendDataUseCase не нужен сразу при создании объекта, а нужен только если пользователь нажмёт на кнопку "Send" в UI, что может и не произойти. Так как эта зависимость нужна в конструкторе, то при получении в DI будет сразу происходить создание этой зависимости, что приводит к ненужной нагрузке. Я рекомендую делать отложенное получение зависимостей с помощью механизма Provider или Lazy. Первый будет ходить за зависимостью в граф каждый раз, а второй - при первом обращении и сохранит её. // При использовании Dagger или Hilt class MyViewModel( ... private val sendDataUseCase: javax.inject.Provider<SendDataUseCase>, // или dagger.Lazy ... ): ViewModel() { fun onSendClicked(...) { viewModelScope.launch { sendDataUseCase.get() .invoke(...) } } } Если вы используете Koin на момент написания поста (актуальная версия 4.0), делать отложенный инжект в конструктор возможности нет: // При использовании Koin class MyViewModel(): ViewModel() { // отложенное получение зависимости в Koin private val sendDataUseCase: SendDataUseCase by inject() fun onSendClicked(...) { viewModelScope.launch { // аналог Provider - получение зависимости каждый раз из графа val sendDataUseCase: SendDataUseCase = getKoin().get() sendDataUseCase.invoke(...) } } } Результат оптимизации ✅ более быстрый старт экранов (зависит от сложности графов) ✅ уменьшение расхода памяти ❌ KOIN потеря явной зависимости в конструкторе. Мне бы очень хотелось увидеть аналог Provider и Lazy в Koin через конструктор, но пока приходится делать свои обертки 😔 #dagger#di#лучшиепрактики

Résultats

38 posts similaires trouvés

Recherche globale générale

Android Broadcast

@android_broadcast · Post #8639 · 05/02/2025 16:15

🤯Не нужно делать инжект всех зависимостей в конструктор Встретил код в проекте: class MyViewModel( ... private val sendDataUseCase: SendDataUseCase, ... ): ViewModel() { // Вызывается, когда пользователь в UI нажмёт на "Send" fun onSendClicked(...) { viewModelScope.launch { sendDataUseCase.invoke(...) // либо sendDataUseCase(...) } } } sendDataUseCase не нужен сразу при создании объекта, а нужен только если пользователь нажмёт на кнопку "Send" в UI, что может и не произойти. Так как эта зависимость нужна в конструкторе, то при получении в DI будет сразу происходить создание этой зависимости, что приводит к ненужной нагрузке. Я рекомендую делать отложенное получение зависимостей с помощью механизма Provider или Lazy. Первый будет ходить за зависимостью в граф каждый раз, а второй - при первом обращении и сохранит её. // При использовании Dagger или Hilt class MyViewModel( ... private val sendDataUseCase: javax.inject.Provider<SendDataUseCase>, // или dagger.Lazy ... ): ViewModel() { fun onSendClicked(...) { viewModelScope.launch { sendDataUseCase.get() .invoke(...) } } } Если вы используете Koin на момент написания поста (актуальная версия 4.0), делать отложенный инжект в конструктор возможности нет: // При использовании Koin class MyViewModel(): ViewModel() { // отложенное получение зависимости в Koin private val sendDataUseCase: SendDataUseCase by inject() fun onSendClicked(...) { viewModelScope.launch { // аналог Provider - получение зависимости каждый раз из графа val sendDataUseCase: SendDataUseCase = getKoin().get() sendDataUseCase.invoke(...) } } } Результат оптимизации ✅ более быстрый старт экранов (зависит от сложности графов) ✅ уменьшение расхода памяти ❌ KOIN потеря явной зависимости в конструкторе. Мне бы очень хотелось увидеть аналог Provider и Lazy в Koin через конструктор, но пока приходится делать свои обертки 😔 #dagger#di#лучшиепрактики

Android Broadcast

@android_broadcast · Post #9569 · 17/10/2025 07:58

‼️Не тяните зависимости из графа сразу! Одна из частых ошибок при использовании DI — получать все зависимости из графа сразу (например, в конструкторе класса). Так делать не стоит 😬 Получение зависимости из графа — это каскадный процесс, и он должен выполняться только в момент использования. Поэтому я всегда рекомендую инжектить зависимости для Dagger/Hilt через Lazy (не путайте с kotlin.Lazy) или Provider. class ViewModel @Inject constructor( // Зависимость получается из графа сразу при создании private val useCase: DataUseCase, // Получаем зависимость из графа каждый раз при обращении Provider.get() private val useCaseFactory: Provider<DataUseCase>, // Получаем зависимость из графа при первом обращении // и затем она кэшируется в Lazy объекте private val useCaseLazy: Lazy<DataUseCase>, ) 💡 Чтобы перейти на Lazy без боли в существующем коде — можно использовать делегаты свойств в Kotlin: // Вариант использования без Lazy class ViewModel @Inject constructor( private val useCase: DataUseCase ) // Миграция на Lazy без потери API совместимости class ViewModel @Inject constructor( useCaseFactory: Lazy<DataUseCase>, ) { private val useCase: DataUseCase by useCaseFactory } И небольшой хелпер, чтобы это работало красиво 👇 // Функция расширения для использования property делегата operator fun <T> Lazy<T>.getValue(thisRef: T, property: KProperty<*>): T = get() Таким образом, вы снижаете нагрузку на DI граф, откладываете инициализацию и избегаете ненужных каскадов при старте компонентов. #di#dagger#hilt#лучшиепрактики

Android Broadcast

@android_broadcast · Post #9343 · 18/07/2025 18:24

🤯Вышел Dagger 2.57 и из полезных изменений там... НИЧЕГО. Просто работают под капотом. Может над поддержкой KSP, может еще над чем Вам нужен Dagger? #dagger#di

Hashtags

Android Broadcast

@android_broadcast · Post #8888 · 02/04/2025 06:00

Разработчик из Ozon делится опытом, как организовали с помощью фич языка Kotlin хранилище Dagger-компонентов, доступное из любого модуля, управляющее их жизненным циклом и забравшее другую рутину на себя. #android#dagger#di

Android Broadcast

@android_broadcast · Post #8708 · 19/02/2025 06:48

🤖Форматируйте дату и время на основе настроек пользователя В большинстве приложений приходится выводить время и дату, но в каком формате сделать это правильнее всего? Логично использовать формат, который применяется для локали пользователя, но в настройках системы пользователь может указывать формат времени и даты для отображения, а значит, ему хотелось бы видеть такой формат везде. Используйте класс android.text.format.DateFormat (ВАЖНО не путать с одноименным классом из пакета java.text) // Получаем текущую дату и время val currentDate: Date = ... // Получаем форматтер для даты, который учитывает региональные настройки пользователя val dateFormatter: java.text.DateFormat = android.text.format.DateFormat.getDateFormat(context) // Форматируем дату val formattedDate = dateFormatter.format(currentDate) // Получаем форматтер для времени, который учитывает настройку 12/24-часового формата val timeFormatter = android.text.format.DateFormat.getTimeFormat(context) // Форматируем время val formattedTime = timeFormatter.format(currentDate) // Получение порядка дня, месяца, года, который определил пользователь // Например ['d', 'M', 'y'] val char[] = android.text.format.DateFormat.getDateFormatOrder(context) val is24Hour = android.text.format.DateFormat.is24HourFormat(context) // Выбираем шаблон форматирования времени val pattern = if (is24Hour) "HH:mm" else "hh:mm a" // Форматируем время согласно выбранному шаблону val formattedTime = DateFormat.format(pattern, currentDate) Такой подход позволяет пользователю работать со временем в привычном формате в вашем приложении, а вам не задумываться какой шаблон времени использовать для форматирования. Если вы не хотите работать со старым Date API, которое есть с самых первый версий Java, то можно получить шаблон для форматирования времени на основе настроек пользователя с помощью android.text.format.DateFormat.getBestDateTimePattern() // Получаем шаблон форматирования для времени. В данном случае шаблон "hm" используется для получения // подходящего шаблона, который учитывает настройки пользователя (12/24-часовой формат). val locale = Locale.getDefault() val pattern: String = android.text.format.DateFormat.getBestDateTimePattern(locale, "hm") // Создаем DateTimeFormatter из Java 9 Date Time API val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern(pattern, locale) // Пример форматирования текущего времени с использованием DateTimeFormatter val formattedTime: String = LocalTime.now().format(dateTimeFormatter) println("Отформатированное время: $formattedTime") #android#лучшиепрактики

Android Broadcast

@android_broadcast · Post #8794 · 13/03/2025 11:04

Сравнение Dagger 2, Dagger Hilt и Koin (4м) Быстрый рассказ про популярные DI для Android. Полезно тем, кто выбирает свой первый DI или сомневается в выборе #android#di

Hashtags

Android Broadcast

@android_broadcast · Post #8910 · 06/04/2025 17:51

Как найти неиспользуемые зависимости в Dagger Component (EN,11м) С помощью Dagger SPI автор написал анализатор графа Dagger c целью поиска неиспользуемых зависимостей и описал подход в статье. Также подход можно использовать для визуализации графа зависимостей, считать разные метрики графа и пр. 🐱Исходный код на GitHub 🔗Альтернативная ссылка #dagger#di#opensource

Android Broadcast

@android_broadcast · Post #9398 · 06/08/2025 06:14

🤖 Сокращение размера APK через удаление неиспользуемых ресурсов Библиотеки от Google и других крупных компаний, как правило, содержат множество ресурсов для различных локалей, версий Android, плотностей экранов и других конфигураций. По умолчанию APK включает все эти ресурсы, даже если они не используются в вашем приложении. 🛒App Bundle позволяет доставлять только необходимые ресурсы, включая локали. Однако, если ваше приложение поддерживает смену языка внутри самого интерфейса, вы, скорее всего, отключаете динамическую доставку языковых ресурсов, чтобы все строки были доступны сразу: // build.gradle.kts android { bundle { // Отключить динамическую доставку ресурсов по локалям language.enableSplit = false density.enableSplit = true abi.enableSplit = true } } Чтобы в APK и App Bundle попали только нужные локали, необходимо явно указать их через фильтр локалей в Android Gradle Plugin: android { androidResources { localeFilters += listOf("en", "ru") } } В результате: ✅ Размер сборки уменьшится ✅ В UI не появятся ресурсы из локалей, которые вы не поддерживаете ✅ Google Play не будет доставлять ресурсы для лишних локалей Ранее вместо androidResources использовали resConfigs и resConfiguration, что позволяло удалять ресурсы не только по локалям, но и в других квалификаторах. Эту возможность пометили как deprecated. Теперь удаление предлагается только по языкам. Указание значений из других квалификаторов игнорируется. 📚 Больше полезных материалов в Базе Знаний Android разработчика от @android_broadcast #android#googleplay#лучшиепрактики

Android Broadcast

@android_broadcast · Post #9542 · 04/10/2025 12:25

⚠️ Работа с зависимостями в Gradle таит множество подводных камней: - Откуда берётся зависимость? - Какие транзитивные зависимости подтянутся вместе с ней? - Как убедиться, что скачался именно тот артефакт, который вы ожидали? Чтобы сборка была стабильной, безопасной и быстрой, стоит придерживаться ряда практик 👇 1️⃣Используйте единый источник зависимостей В больших компаниях принято разворачивать свой Nexus / Artifactory. Он проксирует остальные репозитории (MavenCentral, Google и др.), и для проекта остаётся один источник правды. Это ускоряет сборку (репозиторий ближе и быстрее), а также защищает от случайного скачивания библиотек «из непонятного интернета». 2️⃣Ограничивайте содержимое репозиториев При подключении нескольких репозиториев стоит явно ограничить группы пакетов, которые могут из них подтягиваться. Например, для Google Maven: // settings.gradle.kts dependencyResolutionManagement { repositories { google { mavenContent { includeGroupAndSubgroups("androidx") includeGroupAndSubgroups("com.android") includeGroupAndSubgroups("com.google") includeGroupAndSubgroups("org.chromium.net") includeGroupAndSubgroups("com.crashlytics.sdk") } } mavenCentral() } } Так вы избежите ненужных запросов в «левые» репозитории. 3️⃣Проверяйте скачанные артефакты Gradle поддерживает dependency verification. Это позволяет проверить контрольные суммы загружаемых артефактов и защититься от подмены. 📖 Документация: Dependency Verification Пример gradle/verification-metadata.xml: <verification-metadata> <configuration> <verify-metadata>true</verify-metadata> <verify-signatures>false</verify-signatures> </configuration> <components> <component group="org.apache.pdfbox" name="pdfbox" version="2.0.17"> <artifact name="pdfbox-2.0.17.jar"> <sha512 value="..." /> </artifact> </component> </components> </verification-metadata> 4️⃣Ограничивайте транзитивные зависимости Любая библиотека подтягивает за собой десятки других. Чтобы не получить неожиданное поведение или небезопасные версии — используйте constraints: dependencies { implementation("org.apache.httpcomponents:httpclient") constraints { implementation("org.apache.httpcomponents:httpclient:4.5.3") { because("previous versions have a critical bug") } implementation("commons-codec:commons-codec:1.11") { because("version 1.9 pulled from httpclient has issues") } } } А если нужно зафиксировать версии жёстко: configurations.all { resolutionStrategy { force("org.example:lib:1.2.3") // Есть много других возможностей } } 5️⃣Анализируйте дерево зависимостей Чтобы понять, кто и что тянет, используйте: ./gradlew dependencies ./gradlew dependencyInsight --dependency okhttp --configuration releaseRuntimeClasspath Это поможет отловить дубликаты и неожиданные версии. 6️⃣Автоматизируйте обновления Поддерживайте проект в актуальном состоянии: 🔄 используйте Gradle Versions Plugin, чтобы проверять обновления библиотек. 📝 заведите политику обновлений (например, обновлять минорные версии раз в месяц, а мажорные — отдельно и осознанно). 🔥 В итоге, хорошая стратегия работы с зависимостями — это баланс между удобством разработки и контролем. Чем больше проект и команда, тем жёстче стоит соблюдать правила. #gradle#лучшиепрактики

Android Broadcast

@android_broadcast · Post #8905 · 05/04/2025 13:52

Отключите эти настройки Android в Gradle для ускорения сборки В Android Gradle Plugin есть настройка разных build feature для включения разных опций // Часть флагов могут быть доступны только в определнных типах модулей // Указаны знгачения по умолчанию в Android Gradle Plugin 8.10.0 android { buildFeatures { // Включить/выключить Android ресурсы для библиотечных модулй androidResources = true aidl = false buildConfig = false compose = false dataBinding = false mlModelBinding = false prefab = false renderScript = false // Генерация ресурсов из Gradle файла resValues = true shaders = true viewBinding = false } } Каждая из них отвечает за определенную опцию, но вот значение каждой опции будет зависеть от версии. Я предпочитаю явно выключить все опции по умолчанию и в каждом модуле включать их только при необходимости в модуле в build.gradle.kts. Сделать это можно через gradle.properties # Отключение ресурсов для Android Library модулей android.library.defaults.buildfeatures.androidresources=false android.defaults.buildfeatures.aidl=false android.defaults.buildfeatures.resvalues=false android.defaults.buildfeatures.databinding=false android.defaults.buildfeatures.mlmodelbinding=false android.defaults.buildfeatures.shaders=false android.defaults.buildfeatures.prefabPublishing=false android.defaults.buildfeatures.viewbinding=false ‼️ Больше полезных советов и статей в Базе Знаний Android разработчика #android#gradle#лучшиепрактики

Android Broadcast

@android_broadcast · Post #9349 · 21/07/2025 12:06

🤯Команда Anvil решила прекратить развитие проекта в пользу другого решения Anvil - Kotlin плагина для расширения возможностей Dagger 2 и упрощения работы с ним решили прекратить развивать. Коллега автором решения сделал Metro и компания будет переходить на него и участвовать в его развитии. Metro - это compile-time DI фреймворк с поддержкой KMP, который вдохновлялся Dagger, Anvil, Kotlin-Inject. #di#kmp

Hashtags

Android Broadcast

@android_broadcast · Post #8675 · 12/02/2025 10:13

Не нужно делать UseCase для простых вызовов В статье приводится пример с получением данных через UseCase с простым вызовом метода из единственной зависимости. Конечно, есть принятый подход, но зачем делать лишний класс только потому, что "так принято". Мне не нравится делать так: class FetchMemesUseCaseImpl( private val memeRepository: MemeRepository ) : FetchMemesUseCase { override suspend operator fun invoke(): List<Meme> { return memeRepository.fetchMemes() } class MemeListViewModel( private val fetchMemesUseCase: FetchMemesUseCase ) : ViewModel() а на замену просто получать данные из репозитория в ViewModel: class MemeListViewModel( private val memeRepository: MemeRepository ) : ViewModel() Не делайте избыточный код просто потому, что так принято у всех остальных или потому, что так сказал какой-то умный эксперт по разработке. Оценивайте здраво, что вам нужно сейчас, и при изменении требований вводите новые элементы в архитектуре. #android#архитектура#лучшиепрактики

PrécédentPage 1 sur 4Suivant