fbpx

Blog

Dagger Component Dependencies в многомодульных Android-приложениях

В этой статье мы на примере рассмотрим как создать многомодульное Android-приложение, и помимо этого рассмотрим работу Dagger2 в контексте многомодульных приложений на примере работы Component Dependencies. Но перед тем, как мы начнем, не забудьте подписаться на  Telegram-канал там вы найдете множество полезных материалов для Android-разработчика. Итак, поехали

Основы многомодульности.

Для начала, давайте рассмотрим, для чего вообще нужно разбивать приложение на несколько модулей? Как правило, чаще всего при многомодульной архитектуре выделяют следующие плюсы:

📌 Слабая связность кодовой базы. Изменения в одном модуле не заденут другие фичи. Упрощается количество сайд-эффектов.

📌 Быстрая сборка приложения

📌 Ускорение разработки. Можно работать большой командой параллельно. Можно создать несколько независимых продуктовых команд.

📌 Есть четкие границы ответственности

📌 Легче анализировать и проверять изменения

📌 Возможность переиспользования модуля в другом проекте. Например модуль авторизации, карты, оплата📌 Возможность использовать Dynamic Feature Modules, уменьшив размер apk

Типы модулей

То, как вы организуете модули, в основном зависит от архитектуры вашего приложения. Ниже приведены некоторые распространенные примеры модулей, которые вы можете добавить в свое приложение, следуя рекомендуемой архитектуре Android-приложений.

Data-модули (модули данных).

Data-модуль обычно содержит репозиторий, источники данных и классы моделей. Три основные обязанности data-модуля:

  1. Инкапсуляция, сокрытие данных и бизнес-логики для конкретной предметной области, домена. Каждый data-модуль отвечает за обработку и работу с данными представляющими конкретный домен, предметную область. Он может обрабатывать многие типы данных, если они связаны.
  2. Предоставить репозиторий в качестве внешнего API. Общедоступный API data-модуля должен быть репозиторием, поскольку он отвечает за предоставление данных остальной части приложения.
  3. Скрыть доступ к деталям реализации и Data Source: Источники данных (Data Source) должны быть доступны только репозиториям из того же модуля. Они остаются скрытыми от доступа снаружи. Вы можете обеспечить это, используя ключевое слово private или internal visibility.

Feature-модули. Функциональные модули.

Под фичей (feature) подразумевается изолированная часть функциональности приложения, которая обычно соответствует экрану или набору тесно связанных экранов, таких как процесс регистрации или оформления заказа. Если в вашем приложении есть Bottom Bar для навигации, вполне вероятно, что каждый пункт назначения является отдельной фичей.Фичи (feature) связаны с экранами или местами назначения в вашем приложении. Они, скорее всего, будут иметь связанный пользовательский интерфейс и ViewModel для обработки своей логики и состояния. Примером может быть функционал оплаты, авторизация пользователя. Функциональность не обязательно должна быть ограничена одним экраном или местом навигации. Feature-модули зависят от data-модулей.

App-модули. Модули приложения.

App-модули являются точкой входа в приложение. Они зависят от feature-модулей и обычно обеспечивают корневую навигацию.Если ваше приложение предназначено для нескольких типов устройств, таких как android auto, android wear или android TV, вы можете разделить модули приложения для каждого из устройств. Это помогает отделить зависимости от конкретной платформы.

Common/Core-модули. Общие модули.

Общие модули, также известные как базовые (core) модули, содержат код, который часто используется другими модулями. Они уменьшают избыточность и не представляют какой-либо конкретный уровень в архитектуре приложения. Ниже приведены примеры общих модулей:

  • UI-модуль. Если у вас есть настраиваемые UI-компоненты или сложные брендинг, вы можете выделить UI-виджеты в отдельный модуль для дальнейшего повторного использования. Это поможет сделать UI вашего приложения консистентным. Кроме того, если ваш UI выделен в отдельный модуль, то вы сможете избежать болезненного рефакторинга при ребрендинге.
  • Модуль аналитики: отслеживание различных событий часто диктуется бизнес-требованиями без учета архитектуры программного обеспечения. Трекеры аналитики часто используются во многих несвязанных между собой компонентах. Если это ваш случай, было бы неплохо иметь специальный модуль для аналитики.
  • Сетевой модуль: если многим модулям требуется сетевое подключение, вы можете рассмотреть возможность создания модуля, предназначенного для предоставления http-клиента. Это особенно полезно, когда вашему клиенту требуется индивидуальная конфигурация.
  • Утилитный, служебный модуль: утилиты, различные хэлперы, обычно представляют собой небольшие фрагменты кода, которые повторно используются в приложении. Примеры утилит включают классы по тестированию, функцию форматирования валюты, валидатор для проверки электронной почты.

Способы разбиения приложения на модули

📌 По слоям. Каждый модуль это domain/data/presentation.

📌 По сценариям (по фичам). Каждый модуль – это самостоятельный сценарий или набор пользовательских сценариев, имеющих общую цель. Например: Оплата, Авторизаци

📌 По слоям и фичам. Этот пример иллюстрирует данная картинка:

Dagger 2 в многомодульном приложении

С разбиением на модули думаю понятно, теперь давайте на примере рассмотрим как это реализовать. В качестве примеры мы создадим отдельный Netwrok-модуль, который будет предоставлять инстансы классов для работы с API. Для этого мы воспользуемся Component Dependencies.

Модуль App зависит от модуля CoreNetwork

Давайте создадим отдельный модуль:

File -> New -> New Module

Выбираем Library

Android Library

В итоге должно получится так:

Теперь, вспоминаем основные сущности Dagger 2, а именно Component и Module. Для того чтобы мы могли внедрить зависимости, необходимо прописать provides-методы в Module в модуле core_network

Создаем Dagger Module и описываем необходимые зависимости

Теперь описываем Component в том же модуле core_network

Теперь, когда мы описали Module и Component, необходимо тоже самое сделать в модуле App. Создадим Module, который провайдит репозиторий для нашего приложения

Здесь мы описываем те зависимости, которые понадобятся нам в App-модуле (например для работы ViewModel для запроса). Второй шаг – это описать Component для App-модуля.Для организации взаимодействия мы будем использовать Component Dependecies.Отмечу сразу особенности Component dependencies:

  1. Два зависимых компонента не могут иметь одинаковый scope. Подобнее тут.
  2. Родительский компонент в своем интерфейсе должен явно задавать объекты, которыми могут пользоваться зависимые компоненты.
  3. Компонент может зависеть от нескольких компонент.

Чтобы передать необходимые нам зависимости и в итоге построить AppComponent, необходимо указать через dependencies Component из Core-модуля:

И для того, чтобы мы могли в конечном итоге построить AppComponent нам нужно использовать @Component.Factory – Фабрика — это тип с единственным методом, который возвращает новый экземпляр компонента при каждом вызове.

Создаем AppComponent:

Ну и заключительный шаг, инжектим ViewModelProvider.Factory и получаем через нее ViewModel, с которой уже можно работать.

В свою очередь ViewModel имеет в конструкторе @Inject для репозитория:

Таким образом мы разделили монолитное приложение на 2 модуля core_network и app, используя Component Dependencies. Исходный код вы сможете найти по ссылке на GitHub.https://github.com/AndroidStudentClub/Using-Dagger-in-multi-module-apps

Интенсив по Android-разработке

Чтобы не пропустить новые интересные статьи на тему Android и мобильной разработки подписывайтесь на Telegram-канал