dagger android что это

Dagger 2.11 & Android

В данной статье рассматривается использование специализированного модуля Dagger 2 под android и подразумевается, что у вас есть наличие базовых знаний по Dagger 2.

В Dagger 2.10 был представлен новый модуль специально для Android. Данный модуль поставляется как дополнение, состоящий из дополнительной библиотеки и компилятора.
В версии 2.11 были некоторые небольшие изменения, в частности некоторые классы, были переименованы, поэтому будет использоваться именно эта версия.

Базовая теория

Рассмотрим некоторые особенности Dagger 2, которые будут применяться в примерах.

static @Provides методы

У нас появилась возможность писать статические @Provides методы:

Основное отличие статического @Provides метода от обычного в том, что он дергается компонентом напрямую, а не через инстанс модуля. Статические @Provides методы можно использовать как в абстрактном, так и в обычном классе модуля. Статические методы могут быть scope и unscope.

@Binds

Dagger 2 позволяет нам предоставлять зависимости без наличия @Provides методов. Это достигается путем наличия @Inject над конструктором у класса, который нам необходимо создать.

При таком подходе мы можем писать в качестве типа конкретный класс, мы не можем запросить зависимость по интерфейсу NewsRepository. Dagger 2 не сможет найти нужную реализацию для данного интерфейса.

Теперь мы можем смело писать следующее:

Модули представленные в виде абстрактных классов имеют следующие особенности:

При использовании @Binds + @Inject над конструктором у нас нет необходимости писать и реализовать полностью @Provides методы.

Если в модуле методы только для байндинга ( @Binds ), то имеет смысл сделать этот модуль в виде интерфейса:

Dagger-Android

Типичное android приложение использующая Dagger 2 выглядит примерно так:

Также могут быть получение саб компонентов для разных скоупов (например Activity scope, Fragment scope).

Отсюда вытекают такие проблемы:

Эту проблему решает новый модуль для android.

Подключение зависимостей

Нельзя просто подключить зависимости только относящиеся к android. Они идут как дополнение.

Реализация

Как известно аннотацией @Scope и её наследниками помечаются методы в модулях, а также компоненты/сабкомпоенты, которые предоставляют необходимые нам зависимости.
@Scope определяет время жизни создаваемых(представляемых) объектов, тем самым представляют эффективное управление памятью.

Рассмотрим пример структуры приложения по скоупам:

Приступаем к реализации:

1. Определим наш главный модуль.

В данный модуль было добавлено следующее:

2. MainActivityModule

Пример получение инстанса активити в качестве зависимости.

3. Напишем наш root компонент, который будет содержать наш AppModule, а также единственный инжект в Application.

4. Необходимо реализовать интерфейс HasActivityInjector в Application и заинжектить диспечер AndroidInector’ов.

5. Теперь мы можем всем этим воспользоватся

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

Конструкцию AndroidInjection.inject(this) можно вынести в базовый класс и так же все будет работать.

Нам необходимо обновить наш MainActivityModule :

8. MyFragmentModule

9. Инджектим в фрагмент

Конструкцию AndroidSupportInjection можно вынести в базовый класс.

Вывод

По моему мнению, новый модуль android-dagger предоставляет более правильное предоставление зависимостей для android. Мы можем вынести в базовые классы методы инъекции, получили более удобное разделение по скоупам, нам не надо пробрасывать сабкомпоненты и у нас стали доступны в графе зависимости объекты активити и фрагмента, которые мы можем использовать в качестве внешней зависимости, например в presenter’e.

Источник

Знакомимся с Dependency Injection на примере Dagger


В данной статье мы попытаемся разобраться с Dependency Injection в Android (и не только) на примере набирающей популярность open source библиотеки Dagger
И так, что же такое Dependency Injection? Согласно википедии, это design pattern, позволяющий динамически описывать зависимости в коде, разделяя бизнес-логику на более мелкие блоки. Это удобно в первую очередь тем, что впоследствии можно эти самые блоки подменять тестовыми, тем самым ограничивая зону тестирования.

Несмотря на замудреное определение, принцип довольно прост и тривиален. Я уверен, что большинство из программистов так или иначе реализовывали этот pattern, даже порой об этом не догадываясь.

Читайте также:  что делать если застряла машина в дейз

Рассмотрим упрощенную (до псевдокода) версию Twitter клиента.

В теории, диаграмма зависимостей выглядит примерно так:

Давайте взглянем как это выглядит в коде:

Как видим, набор интерфейсов довольно прост, поэтому использовать мы это будем примерно так:

Пока все идет хорошо, твиты улетают — все счастливы. Теперь возникает необходимость все это протестировать. Сразу же замечаем, что неплохо было бы иметь возможность подменять Http клиент на тестовый, чтобы возвращать какой-нибудь тестовый результат и не ломиться в сеть каждый раз. В этом случае, нам надо снять с класса TwitterApi обязанность создавать Http клиент и сгрузить эту обязанность вышестоящим классам. Наш код немного преображается:

Теперь мы видим, что при необходимости простестировать наш код, мы можем легко «подставить» тестовый Http клиент, который будет возвращать тестовые результаты:

Казалось бы, что может быть проще? На самом деле, сейчас мы «вручную» реализовали Dependency Injection паттерн. Но есть одно «но». Представим ситуацию, что у нас есть класс Timeline, который умеет загружать последние n сообщений. Этот класс тоже использует TwitterApi:

Наш класс выглядит примерно так:

Вроде бы все ничего — мы применили тот же подход, что и с классом Tweeter — дали возможность указывать Http клиент при создании объекта, что позволяет нам протестировать этот модуль, не завися при этом от сети. Но! Вы заметили, сколько кода мы продублировали и как нам приходится «протаскивать» Http клиент прямо из «головы» приложения? Конечно, можно добавить конструкторы по умолчанию, которые будут создавать реальный Http клиент, и использовать кастомный конструктор только при тестировании, но ведь это не решает проблему, а только маскирует ее.

Давайте рассмотрим как мы можем улучшить сложившуюся ситуацию.

Dagger

Dagger — это open source Dependency Injection библиотека от разработчиков okhttp, retrofit, picasso и многих других замечательных библиотек, известных многим Android разработчикам.

Запрос зависимостей (request dependency)

Чтобы попросить Dagger проиницализировать одно из полей, все что нужно сделать — добавить аннотацию @Inject :

… и убедиться, что этот класс добавлен в граф зависимостей (об этом далее)

Удовлетворение зависимостей (provide dependency)

Чтобы сказать даггеру какой инстанс клиента необходимо создать, необходимо создать «модуль» — класс аннотированный @Module :

Этот класс отвечает за «удовлетворение» части зависимостей, запрошенных приложением. В этом классе нужно создать так называемый «провайдер» — метод, который возвращает инстанс HttpClient (аннотированный @Provide ):

Этим мы сказали Dagger’y, чтобы он создал OkHttpClient для любого, кто попросил HttpClient посредством @Inject аннотации

Стоит упомянуть, что для того, чтобы compile-time валидация работала, необходимо указать все классы (в параметре injects), которые просят эту зависимость. В нашем случае, HttpClient необходим только TwitterApi классу.
Аннотация @Singleton указывает Dagger’у, что необходимо создать только 1 инстанс клиента и закэшировать его.

Cоздание графа

Теперь вернемся к запросу зависимостей:

Теперь вернемся к нашей изначальной задаче — протестировать все. Нам необходимо каким-то образом уметь подменять HttStack. За удовлетворение этой зависимости (хмм — только сейчас заметил как это интересно звучит) отвечает модуль NetworkModule:

Один из вариантов — это добавить какой-нибудь конфигурационный файл, который будет диктовать какой environment использовать:

Но есть вариант еще элегантней. В Dagger можно создавать модули, переопределяющие функции, предоставляющие зависимости. Для этого в модуль надо добавить параметр overrides=true :

Все что остается сделать — это добавить этот модуль в граф на этапе инициализации:

Теперь все наши запросы будут идти через тестовый Http клиент.

Это далеко не все фичи Dagger’a — я описал только один из возможных сценариев использования данной библиотеки. В любом случае, без вдумчивого прочтения документации не обойтись.

Источник

Dagger 2 – это элементарно (Часть 1)

Введение

Что такое Dependency Injection

Dependency Injection (инъекция или внедрение зависимости) — это зависимость одного класса от другого. т.е. для полноценной работы одного класса нужна инициализация другого(их) класса.

Например, класс Car (автомобиль) не может работать без класса Engine (Мотор) который в свою очередь не может работать без класса Fuel (Топливо). Выглядит это так:

Читайте также:  судьба марии содержание чем закончится

В данном примере класс Car зависит от класса Engine а тот в свою очередь от класса Fuel.

Dagger 2 – введение

Dagger это библиотека которая помогает реализовать «внедрение зависимости:. Это библиотека google. Подробную документацию можно получить тут.

Первое использование Dagger 2

В первую очередь нужно добавить dagger в приложение. Знаю 2 методов как это можно сделать
1. Открыть build.gradle (App) и добавить след.

1.1 В самом верху в разделе объявления plugin

1.2 в разделе dependencies

версию dagger (dagger_version) указываю в разделе

Если такого еще нет, раздел нужно добавить над разделом android.

2. Добавить Maven репозиторий через Project Structure — Dependencies — Add library dependencies

После синхронизации проекта мы готовы к внедрению зависимостей при помощи dagger.

В первую очередь создадим классы Car, Engine и Fuel:

Перед констракторами классов Car, Engine и Fuel добавим аннотация dagger Inject, тем самым дадим понять dagger что эти классы должны быть внедрены при необходимости. Получаем след.

Dagger должен знать как создавать все объекты которые он должен внедрять. Для того чтоб перечислить все классы которые мы внедряем (Inject) используется аннотация Component которая объявляется для интерфейса (DaggerComponent).

при объявлении методов компонента важны не названия методом а возвращаемый ими класс.

На этом шаге нужно собрать проект (Build — Rebuild project). После этого dagger сгенерирует необходимые классы и фабрику для инициализации компонентов. Название фабрики будет совпадать с названием интерфейса в которой мы инициализируем классы для даггер за исключением того что будет добавлен префикс „Dagger“, т.е. на выходе получим класс DaggerDaggerComponent.

Все готово. Попробуем создать поле car типа Car в MainActivity:

Запустив приложение можно убедиться что поле car инициализируется при обращении к нему

Источник

Dagger 2 для начинающих Android разработчиков — Введение

Данная статья является первой частью серии статей, предназначенных, по словам автора, для тех, кто не может разобраться с внедрением зависимостей и фреймворком Dagger 2, либо только собирается это сделать. Оригинал написан 18 ноября 2017 года. Изображения и GIF — из оригинала. Перевод вольный.

Dagger 2 — это полностью статический фреймворк для внедрения зависимостей в Java и Android, работающий во время компиляции. Dagger 2 — это адаптация созданного ранее компанией Square фреймворка Dagger, поддерживаемая компанией Google.

Для кого эта статья?

Если вы начинающий Android разработчик, изучающий непосредственно Android и параллельно получающий знания по Java, то данная статья для вас. Если вы пытались изучать Dagger 2 и то, что вы находили в интернете казалось вам немного сложным — не беспокойтесь, я тоже прошел через это (все мы немного особенные, каждому требуется свой подход в объяснении чего-либо) и эта статья определенно для вас. Если вы уже знакомы с внедрением зависимостей и Dagger, то вы сможете узнать что-нибудь новое или прояснить для себя некоторые вещи.

Серия статей

Требования

Предполагается, что вы уже знакомы с языком программирования Java, принципами ООП и Android разработкой.

Что такое зависимость?

Замечание: для объяснения данной концепции я буду использовать аналогии с телесериалом «Игра престолов». Если вы не знакомы с данным сериалом, то можете заменять имена классов на более удобные для вас. И вы должны обязательно начать смотреть этот сериал.

Чем плохи зависимости?

Большое количество зависимостей в классе приводит к проблемам сильных связей (hard dependency), что плохо по следующим причинам:

#Повторное использование (reusablility)

Когда классы и методы слабо связаны, не связаны или не зависят от множества других — возможности повторного использования кода возрастают. Повторное использование кода — одна из базовых идей объектно-ориентированного программирования.

#Тестирование

#Поддерживаемость (maintainability)

Когда код не может быть корректно протестирован, его части невозможно или сложно повторно использовать, а проект продолжает расти, тогда проект становится очень сложно поддерживать. Поддерживаемость зависит от множества других факторов, но пока новые разработчики в вашей команде понимают систему и делают работу коллег комфортнее, то ваш проект всё ещё поддерживаемый.

Читайте также:  что делать если воспалился карман в десне

Типы зависимостей

Есть множество типов зависимостей, но можно выделить основные:

#Зависимость от классов

#Зависимость от интерфейсов

Метод executePlan принимает интерфейс WarStrategy как зависимость. WarStrategy может быть реализован всеми домами (Targaryens, Starks, Lannisters и так далее).

#Зависимость от методов или полей

#Прямые и косвенные зависимости

Резюме

Зависимости плохи тем, что уменьшают возможности повторного использования кода, а также усложняют процесс тестирования, из-за чего поддерживать проект становится сложнее.

Зависимости могут быть различных типов: классовые, интерфейсные, от методов, от полей, прямые, косвенные и другие.

Источник

Dagger 2.11 & Android. Часть 2

В предыдущей статье мы рассмотрели, как мы можем использовать специальный модуль dagger-android для предоставления зависимостей в активити и фрагменты, а также организацию разных скоупов.

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

Модуль dagger-android позволяет заинжектить зависимости в следующие базовые компоненты андроида:

Activity, Fragment, Service, DaggerIntentService, BroadcastReceiver, ContentProvider.

Если мы используем классы из библиотеки поддержки (например AppCompatActivity, android.support.v4.app.Fragment ), то нам надо использовать соответствующие классы из дополнительной даггер библиотеки поддержки (dagger-android-support).

AndroidInjector

Служит для инъекций зависимостей в наследников базовых компонентов ( Activity, Fragment, и т.д. ).

@ContributesAndroidInjector

Данная аннотация должна быть применена над абстрактным методом в модуле, где возвращаемый тип метода — это наследник базового компонента андроид( Activity, Fragment и т.д. ). Метод не должен иметь параметров.

Данная аннотация служит для генерации AndroidInjector для возвращаемого типа метода, над которым указана аннотация. Данный AndroidInjector является сабкомпонентом. Этот сабкомпонент является дочерним того компонента (или сабкомпонента), в который данный модуль(в котором присутствует данная аннотация) будет добавлен.

Над методом с аннотацией @ContributesAndroidInjector также может присутствовать аннотация скоупа. Данный скоуп будет применен к сгенерированному сабкомпоненту.

AndroidInjectionModule / AndroidSupportInjectionModule

DispatchingAndroidInjector

AndroidInjection / AndroidSupportInjection

Класс утилита, имеет перегруженный метод inject для всех базовых типов ( Activity, Fragment, Service и т.д. ). В зависимости от переданного типа, ищет реализацию одного из следующих интерфейсов:

AndroidInjection.inject() должен быть вызван в определенном методе, до вызова супер метода:

Dagger-android имеет классы, которые мы можем использовать (эти классы уже реализуют необходимые интерфейсы и вызов метода AndroidInjection.inject() ):

Если по каким то причинам мы не можем расширить один из этих классов, то мы всегда можем реализовать необходимый интерфейс.

Примеры использования dagger-классов:

Определим основной модуль

В данном модуле мы добавим «маппинг» для нашей активити, сервиса и бродкаст ресивера. Для них будет сгенерированы сабкомпоненты и будут добавлены к основному компоненту, т.к. этот модуль мы подключили к основному компоненту.

Определим наш класс Application

Пример с Activity

Пример с IntentService

Пример с Receiver

Component lifecycle

При использовании dagger-android, компоненты и сабкомпоненты живут на протяжении жизни андроид компонентов( Activity, Fragment, Service и т.д.) в которых они были созданы и дестроить вручную их не надо. К примеру активити сабкомпоент создается в момент вызова AndroidInjection.inject() и живет до тех пор пока активити не уничтожена.

Dynamic parameters

Вариант 1:
Установка параметров в объект, где он используется.

Данный вариант не подходит для immutable классов.

Перестроить сам класс таким образом, чтобы он не принимал динамические параметры при создании, а сам параметр использовать через методы:

Реализовать создание объекта с динамическими параметрами с помощью фабрики:

Написание подобных фабрик может оказаться не удобным или занимать некоторое время, для решение этой проблемы можно посмотреть в сторону AutoFactory.

Есть еще решение от Fernando Cejas, больше подходящее для тех, кто использует RxJava:
Dynamic Parameters in Use Cases

Вывод

Dagger-android позволяет предоставлять зависимости в базовые компоненты андроид ( activity, fragment, service и т.д.) более удобным способом, избавляет нас от создания сабкомпонентов и контроля за ними. Активити, фрагменты, сервисы и т.д. выглядят более “чистыми”.

Надеюсь, данная статья помогла вам больше разобраться с возможностями dagger-android.

Источник

Сказочный портал