В качестве примера возьмем простое Android-приложение, состоящее только из одного Activity. В нем создадим 2 компонента Dagger: ApplicationComponent, жизненный цикл которого совпадает с жизненным циклом приложения, и ActivityComponent, жизненный цикл которого совпадает с жизненным циклом Activity. Как известно, при смене конфигурации, Activity пересоздается, поэтому ActivityComponent также будет пересоздаваться. Также, нам в ActivityComponent, возможно, понадобятся зависимости из ApplicationComponent, поэтому сделаем ActivityComponent субкомпонентом ApplicationComponent.
Для начала объявим ApplicationScope и ActivityScope:
Теперь объявим ApplicationComponent и ActivityComponent
Далее объявим наследника от класса Application, создадим ApplicationComponent в его методе onCreate и сохраним созданный объект в поле наследника класса Application.
Теперь перейдем в MainActivity, создадим в методе onCreate ActivityComponent и запросим зависимости с помощью метода inject:
Но пока нам нечего инджектить, поэтому создадим демонстрационный класс Example:
При каждом создании объекта класса Example, ему будет присвоен уникальный идентификатор, который поможет нам в последующем понять создал ли нам Dagger новый объект этого класса или переиспользовал старый.
Теперь вернемся в MainActivity, добавим поле example, которое мы будем запрашивать у Dagger через ActivityComponent, и напишем вывод в лог идентификатора объекта:
Запустим приложение и получим вывод в лог:
Теперь повернем экран, чтобы активити пересоздалось и снова запросило зависимости. Получаем:
Как и ожидалось, Dagger создал новый объект при повторном запросе зависимостей.
Теперь укажем ActivityScope для класса Example:
Но поведение не поменяется. При каждом повороте экрана, Dagger будет создавать новый объект. Потому что при пересоздании Activity, ActivityComponent также пересоздается. Но мы почуствуем разницу, если захотим переиспользовать объект класса Example в пределах жизненного цикла Activity, то есть до того, как оно будет пересоздано. Для этого объявим класс ExampleHolder, который запрашивает объект класса Example через конструктор:
Теперь добавим поле exampleHolder в MainActivity и выведем в лог идентификатор объекта example, который он содержит:
Посмотрим лог:
Перевернем экран:
Мы видим, что в пределах одного Activity используется один и тот же объект. Это потому что мы задали ему скоуп который совпадает со скоупом ActivityComponent. Если мы сотрем скоуп у класса Example, то получим:
А после пересоздания экрана:
То есть объект не переиспользуется, а создается каждый раз, когда запрашивается.
Вспомним, что ActivityComponent является субкомпонентом ApplicationComponent, который создается только один раз — при создании приложения. А значит его жизненный цикл совпадает с жизненным циклом всего приложения. Давайте попробуем указать для класса Example скоуп ApplicationScope и посмотрим, что у нас получится.
Вывод в лог будет следующий:
А после пересоздания экрана:
Как видим, Dagger не создает новый объект при пересоздании Activity, а переиспользует один и тот же объект в пределах жизненного цикла всего приложения.