Site icon AppTractor

Осваиваем ViewModel в Android: «можно» и «нельзя» — Часть 3

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

В предыдущих частях мы обсудили:

  1. Избегайте инициализации состояния в блоке init{}.
  2. Избегайте раскрытия мутабельных состояний.
  3. Используйте update{} при использовании MutableStateFlows.

В этой части мы обсудим 4 и 5 пункты из списка:

  1. Старайтесь не импортировать зависимости Android в ViewModel.
  2. Лениво внедряйте зависимости в конструктор.
  3. Примите более реактивное и менее императивное программирование.
  4. Избегайте инициализации ViewModel из внешнего мира.
  5. Избегайте передачи параметров из внешнего мира.
  6. Избегайте жесткого прописывания диспетчеров корутинов.
  7. Проводите модульное тестирование своих ViewModel.
  8. Избегайте раскрытия suspended функций.
  9. Используйте обратный вызов onCleared() во ViewModel.
  10. Обрабатывайте смерть процесса и изменения конфигурации.
  11. Вставляйте UseCases, которые вызывают Репозитории, которые, в свою очередь, вызывают DataSource.
  12. Включайте в ViewModel только доменные объекты.
  13. Используйте операторы shareIn() и stateIn(), чтобы избежать многократных обращений к восходящему потоку.

4. Старайтесь не импортировать зависимости Android во ViewModel

Рекомендация избегать импорта зависимостей Android во ViewModel, за особыми исключениями для таких классов, как LiveData и его трансформеров, основана на принципах чистой архитектуры и тестируемости. Ниже мы объясним, что это значит и почему это важно.

1. Разделение ответственности

Но что, если мне нужно выдать какую-то строку из вью-модели как часть состояния?

Для таких случаев идеальным вариантом будет использование изолированного (sealed) интерфейса Kotlin, подробнее об этом читайте в этой статье.

2. Тестируемость

3. Переносимость

Код, который не зависит напрямую от фреймворка Android, более переносим и прост в сопровождении. Его можно повторно использовать в разных частях приложения или даже в других проектах с минимальными изменениями. И даже в будущем вью-модели можно будет легко заменить, например, на Circuit Presenters из Slack, чтобы перенести вашу кодовую базу на Kotlin MultiPlatform.

А как же LiveData и трансформеры

5. Лениво внедряйте зависимости в конструктор

Инжектирование зависимостей непосредственно в конструкторы ViewModel без ленивой инициализации может привести к:

  1. увеличению времени запуска
  2. повышенному использованию памяти
  3. излишней загрузке процессора

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

Неиспользование ленивой инициализации для зависимостей в конструкторах ViewModel может повлиять на производительность и использование ресурсов Android-приложения, особенно во время запуска или при создании экземпляров этих ViewModel. Ниже обсудим, как неленивая инъекция сравнивается с ленивой и почему последняя часто предпочтительнее в определенных сценариях.

Когда следует использовать ленивую инициализацию

Пример

@HiltViewModel
class BookViewModel @Inject constructor(
    @IoDispatcher private val ioDispatcher: CoroutineDispatcher,
    private val bookmarkUseCase: dagger.Lazy<BookmarkUsecase>,

Представьте, что в вашей ViewModel есть действие с закладкой, которое сработает, если пользователь нажмет на кнопку закладки. Для этой зависимости, которая внедряется через конструктор BookViewModel, мы можем использовать ленивую инъекцию, которая отложит создание Usecase до тех пор, пока он не понадобится.

Источник

Exit mobile version