Изначально я планировал в рамках своего курса Dagger написать урок про использование даггера в мультимодульном проекте. Но быстро понял, что одним уроком тут не обойтись. Более того, стало понятно, что материал получается большой и достаточно полезный для новичков. В итоге я решил оформить все это отдельной серией статей в открытом доступе.

 

 

Чтобы понимать, о чем пойдет речь, рекомендуется иметь базовые знания даггера. В моем курсе открыты первые несколько уроков. Это необходимый минимум. А также желательно знать про сабкомпоненты и примерно понимать, что такое scope.

 

 

О чем будем говорить

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

Цель этой серии статей - дать понимание, как работает даггер в мультимодульном проекте. Для начинающих разработчиков обе этих темы не являются простыми. А вместе они представляют собой комбо в виде черного ящика, в котором совершенно непонятно что происходит.

Чтобы разобраться, как оно все работает, мы по шагам будем создавать 5-модульное приложение. В одном из этих модулей (не app) создадим фрагмент, в который компонент будет инджектить объекты. В последних уроках мы рассмотрим три варианта реализации компонента:
- AppComponent, расположен в app модуле
- сабкомпонент от AppComponent, расположен в модуле фрагмента
- отдельный компонент с dependencies, расположен в модуле фрагмента

Выясним, в чем разница между этими вариантами.

Кроме этого, мы будем использовать свою реализацию компонентов вместо даггеровской, чтобы понимать, как все это работает под капотом.

Полученные знания позволят вам лучше разбираться в темах Dagger и мультимодульность. Вам будет проще читать и понимать статьи, в которых описаны рабочие варианты использования даггера в мультимодульном проекте. И это поможет вам придумать реализацию, которая подходит вашему проекту.

 

Чтобы лучше усвоить материал, рекомендую вам создать новый проект и выполнять все шаги. Кода будет немного. Мы будем только инджектить объекты в Activity и фрагменты. А сами классы будут пустыми и не будут ничего делать. Также здесь не будет никакой архитектуры, презентеров, ViewModel и прочего, чтобы не усложнять.

 

Создание проекта

Давайте переходить к практике. Будем создавать приложение Менеджер задач.

 

Создаем новый пустой проект со стандартным модулем app и MainActivity в нем. Для отображения списка задач мы хотим использовать отдельное Activity. Потом переделаем на фрагмент, не волнуйтесь )

Создаем TaskActivity в app модуле.

TasksActivity (:app)

class TasksActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_tasks)
   }
}

Обратите внимание, при публикации фрагментов кода я указываю имя файла и в скобках имя модуля, в котором этот класс находится

 

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

 

Создаем модуль data. В меню студии: File > New > New Module

Все создаваемые модули будем создавать с типом Android Library

Package name у вас будет другой

После некоторых размышлений студия должна показать новый модуль в списке слева, на одном уровне с app

 

В модуле data создаем класс для работы с базой данных:

Database (:data)

class Database{
}

Расположение (package) классов в модуле выбирайте любое, подходящее под вашу религию ) Сейчас это не имеет значения.

 

Итак, теперь у нас в проекте есть два модуля: app и data. Между ними пока нет никаких зависимостей. Они не знают друг про друга.

 

В этих модулях есть классы TasksActivity и Database

 

Класс Database мы хотим использовать в TasksActivity. Давайте пока без даггера попробуем сами создавать его там.

TasksActivity (:app)

Студия подсказывает, что Activity ничего не знает про такой класс. И просто добавить импорт тут не получится. Потому что Activity лежит в модуле app, а Database - в модуле data. И эти модули ничего друг про друга не знают.

На схеме это можно изобразить так

Я закрасил стрелку красным цветом, чтобы показать, что класс Database планирует быть использованным в TasksActivity, но пока не может.

 

Отдельно стоит пояснить про направление стрелок. Если объект A использует B, то некоторые рисуют стрелку от A к B, а некоторые - наоборот от B к A.

У первых стрелка имеет значение: “использует”. Т.е. стрелка от A к B означает, что A использует B.

У вторых стрелка имеет значение: “используется в”. Т.е. стрелка от B к A означает, что B используется в A.

Я буду использовать второй вариант, потому что он более подходит к теме даггера. Стрелка показывает какой объект куда будет инджектиться. Т.е. если стрелка от B к A, это значит, что даггер должен инджектить B в A.

В нашем случае стрелка от Database к TasksActivity значит, что Database используется в TasksActivity, и даггеру надо будет инджектить Database в TasksActivity.

 

Итак. Чтобы класс Database из модуля data можно было использовать в классе TasksActivity из модуля app, необходимо, чтобы модуль app знал про модуль data.

Для этого добавляем dependencies в build.gradle модуля app

build.gradle (:app)

implementation project(path: ':data')

и синхронизируем gradle

 

Теперь схема модулей выглядит так

Модуль app знает про модуль data. Классы из data теперь видны в классах из app.

 

После создания этой зависимости студия предложит добавить import

TasksActivity (:app)

 

И мы сможем использовать Database в TasksActivity

Именно для этого и нужны зависимости между модулями.

 

Созданный нами модуль data не стоит рассматривать как какую-то очень сложную штуку типа отдельного подпроекта в основном проекте. Это скорее похоже на продвинутый package, который ограничивает видимость своих классов.

Т.е. TasksActivity и Database - это все еще классы, находящиеся в одном проекте. Просто по умолчанию они скрыты друг от друга. Чтобы Database можно было использовать в TasksActivity, мы в build.gradle явно прописали что классы из модуля data должны быть видны классам из модуля app.

 

 

Результат

Кратко резюмируем, что у нас получилось. Мы создали простое приложение с двумя модулями app и data. В модуле app у нас TasksActivity, а в модуле data - Database. Чтобы TasksActivity могло использовать Database, мы добавили зависимость модуля app от data.

Следующим шагом будет подключение даггера к проекту и его использование для инджекта Database в TasksActivity.


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

- новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме 




Language

Автор сайта

Дмитрий Виноградов

Подробнее можно посмотреть или почитать.

Никакие другие люди не имеют к этому сайту никакого отношения и просто занимаются плагиатом.

Социальные сети

 

В канале я публикую ссылки на интересные и полезные статьи по Android

В чате можно обсудить вопросы и проблемы, возникающие при разработке



Группа ВКонтакте



Поддержка проекта

Яндекс
410011180491924

WebMoney
R248743991365
Z551306702056

Paypal