Внедрение зависимостей — это шаблон проектирования программного обеспечения, направленный на то, чтобы сделать наши приложения слабосвязанными, расширяемыми и обслуживаемыми. Из этого руководства вы узнаете, как обрабатывать внедрение зависимостей с помощью Dagger 2.
Вступление
Когда у вас есть объект, который нуждается или зависит от другого объекта для выполнения своей работы, у вас есть зависимость. Зависимости можно решить, позволив зависимому объекту создать зависимость или попросив фабричный объект создать ее. Однако в контексте внедрения зависимостей зависимости передаются классу, который нуждается в зависимости, чтобы избежать необходимости создания самим классом. Таким образом, вы создаете слабосвязанное и легко обслуживаемое программное обеспечение.
В этом руководстве используется новейшая версия Dagger, Dagger 2 . На момент написания Dagger 2 еще не был официально выпущен и находится на стадии пре-альфа. Тем не менее, он пригоден для использования и стабильный. Вы можете посетить Dagger на GitHub для получения новостей о проекте и возможных датах официального релиза.
Предпосылки
Вам понадобится последняя версия Android Studio, установленная на вашем компьютере для разработки, которую вы можете скачать с сайта Android Developer .
1. Dagger 2 API
Dagger 2 предоставляет ряд специальных аннотаций:
- 
 @Moduleдля классов, чьи методы предоставляют зависимости
-   @Providesметоды в классах@Module
-   @Injectдля запроса зависимости (конструктор, поле или метод)
-   @Component— это мостовой интерфейс между модулями и инжекцией.
Это наиболее важные аннотации, которые вам необходимо знать, чтобы начать работу с внедрением зависимостей с помощью Dagger 2. Я собираюсь показать вам, как использовать их в простом приложении для Android.
2. Кинжал 2 Рабочий процесс
Чтобы правильно реализовать Dagger 2, вы должны выполнить следующие шаги:
- Определите зависимые объекты и их зависимости.
-   Создайте класс с аннотацией @Module, используя аннотацию@Providesдля каждого метода, который возвращает зависимость.
-   Запросите зависимости в ваших зависимых объектах, используя аннотацию @Inject.
-   Создайте интерфейс с @Componentаннотации@Componentи добавьте классы с аннотацией@Moduleсозданной на втором шаге.
-   Создайте объект интерфейса @Componentчтобы создать экземпляр зависимого объекта с его зависимостями.
Анализ зависимостей переносится со времени выполнения на время компиляции. Это означает, что вы будете уведомлены о возможных проблемах на этапе разработки, в отличие от других библиотек, таких как Guice . Перед использованием библиотеки Dagger 2 необходимо подготовить установку Android Studio для доступа к сгенерированным классам.
3. Настройка среды Android Studio
Шаг 1
Создайте новое приложение с помощью Android Studio и присвойте ему имя. Я назвал свой проект TutsplusDagger .

Шаг 2
Установите минимальный SDK для проекта на API 10, чтобы охватить как можно больше устройств.

Шаг 3
Выберите макет бланка для создаваемой вами деятельности. Для этого урока вам не нужен специальный макет.

Шаг 4
  Назовите действие MainActivity и нажмите « Готово» . 

После создания проекта вам необходимо внести несколько изменений в файлы Gradle. Давайте внесем эти изменения в следующем шаге.
4. Настройка Gradle Setup
Шаг 1
Нам нужно изменить файл build.gradle проекта, как показано ниже.
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 | buildscript {     repositories {         jcenter()     }     dependencies {         classpath ‘com.android.tools.build:gradle:1.0.0’         classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.4’     } } allprojects {     repositories {         mavenCentral()         maven{             url ‘https://oss.sonatype.org/content/repositories/snapshots/’         }     } } | 
Давайте на минутку посмотрим, какие изменения мы внесли:
- зависимости: в этом разделе я добавил плагин, который будет полезен для доступа к коду, сгенерированному Dagger. Если вы этого не сделаете, вы увидите ошибки при обращении к этим новым классам.
- allprojects: Это изменение необходимо, поскольку библиотеки, которые мы собираемся использовать, в настоящее время находятся в пре-альфа, и это единственное доступное место, если вы хотите получить к ним доступ с помощью Maven. Вы можете попробовать загрузить библиотеки Dagger и Dagger Compiler из Sonatype, но это руководство основано на репозиториях Maven.
Шаг 2
Откройте build.gradle в папке приложения вашего проекта и измените его, как показано ниже.
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | apply plugin: ‘com.android.application’ apply plugin: ‘com.neenbedankt.android-apt’ android {     compileSdkVersion 21     buildToolsVersion «21.1.2»     defaultConfig {         applicationId «com.androidheroes.tutsplusdagger»         minSdkVersion 10         targetSdkVersion 21         versionCode 1         versionName «1.0»     }     buildTypes {         release {             minifyEnabled false             proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’         }     } } dependencies {     compile fileTree(dir: ‘libs’, include: [‘*.jar’])     compile ‘com.android.support:appcompat-v7:21.0.3’     compile ‘com.google.dagger:dagger:2.0-SNAPSHOT’     apt ‘com.google.dagger:dagger-compiler:2.0-SNAPSHOT’     provided ‘org.glassfish:javax.annotation:10.0-b28’ } | 
В начале файла я применяю новый плагин. Обязательно поместите новый плагин ( com.neenbedankt.android-apt ) ниже или после плагина Android. Если вы этого не сделаете, то при попытке синхронизировать проект с файлами Gradle будут отображаться ошибки.
В зависимости я добавил:
- библиотека кинжалов
- dagger-компилятор для генерации кода
- javax.annotation для дополнительных аннотаций требуется вне Dagger
После обновления конфигурации Dagger вы можете синхронизировать проект с файлами Gradle, нажав кнопку вверху.

На данный момент у вас есть пустой проект, готовый для использования в вашем приложении. Если вы видите какие-либо ошибки, убедитесь, что вы правильно выполнили вышеуказанные шаги. Теперь мы можем приступить к реализации нашего примера проекта.
5. Реализация Dagger 2
Шаг 1: Определите зависимые объекты
  В этом уроке я собираюсь работать с двумя классами: « Vehicle и « Motor .  Motor это независимый класс и Vehicle    это зависимый класс.  Я собираюсь начать создавать эту модель в новом пакете под названием model . 
  Вот как выглядит класс Motor : 
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package com.androidheroes.tutsplusdagger.model; /**  * Created by kerry on 14/02/15.  */ public class Motor {     private int rpm;     public Motor(){         this.rpm = 0;     }     public int getRpm(){         return rpm;     }     public void accelerate(int value){         rpm = rpm + value;     }     public void brake(){         rpm = 0;     } } | 
  Этот класс имеет только один атрибут rpm , который я собираюсь изменить с помощью методов accelerate и brake .  И я проверю текущее значение, используя метод getRpm . 
  Вот как выглядит класс Vehicle : 
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package com.androidheroes.tutsplusdagger.model; /**  * Created by kerry on 14/02/15.  */ public class Vehicle {     private Motor motor;     public Vehicle(Motor motor){         this.motor = motor;     }     public void increaseSpeed(int value){         motor.accelerate(value);     }     public void stop(){         motor.brake();     }     public int getSpeed(){         return motor.getRpm();     } } | 
  В этом классе вы можете видеть, что я не создаю новый объект класса Motor , хотя я использую его методы.  В реальном приложении у этого класса должно быть больше методов и атрибутов, но давайте пока оставим это простым. 
  Шаг 2: Создать класс @Module 
  Теперь вам нужно создать класс с аннотацией @Module .  Этот класс будет предоставлять объекты, которые вам понадобятся, с удовлетворенными зависимостями.  Для этого вам нужно создать новый пакет (просто чтобы он был в порядке), назвать его module и добавить в него новый класс следующим образом: 
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package com.androidheroes.tutsplusdagger.module; import com.androidheroes.tutsplusdagger.model.Motor; import com.androidheroes.tutsplusdagger.model.Vehicle; import javax.inject.Singleton; import dagger.Module; import dagger.Provides; /**  * Created by kerry on 14/02/15.  */ @Module public class VehicleModule {     @Provides @Singleton     Motor provideMotor(){         return new Motor();     }     @Provides @Singleton     Vehicle provideVehicle(){         return new Vehicle(new Motor());     } } | 
  Как я указал в шаге 1 ,    Vehicle нуждается в Motor чтобы работать должным образом.  Вот почему вам нужно создать двух провайдеров, одного для Motor (независимая модель) и другого для Vehicle (с указанием его зависимости) . 
  Не забывайте, что каждый поставщик (или метод) должен иметь аннотацию @Provides а класс должен иметь аннотацию @Module .  Аннотация @Singleton указывает, что будет только один экземпляр объекта. 
  Шаг 3: Запрос зависимостей в зависимых объектах 
  Теперь, когда у вас есть поставщики для ваших различных моделей, вам нужно запросить их.  Так же, как Vehicle нуждается в Motor , вы должны добавить аннотацию @Inject в конструкторе Vehicle следующим образом: 
| 1 2 3 4 | @Inject public Vehicle(Motor motor){     this.motor = motor; } | 
  Вы можете использовать аннотацию @Inject для запроса зависимостей в конструкторе, полях или методах.  В этом случае я сохраняю инъекцию в конструкторе. 
  Шаг 4: Подключение @Modules с @Inject 
  Связь между поставщиком зависимостей @Module и классами, запрашивающими их через @Inject , осуществляется с помощью @Component , который является интерфейсом: 
 
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | package com.androidheroes.tutsplusdagger.component; import com.androidheroes.tutsplusdagger.model.Vehicle; import com.androidheroes.tutsplusdagger.module.VehicleModule; import javax.inject.Singleton; import dagger.Component; /**  * Created by kerry on 14/02/15.  */ @Singleton @Component(modules = {VehicleModule.class}) public interface VehicleComponent {     Vehicle provideVehicle(); } | 
  Рядом с аннотацией @Component вы должны указать, какие модули будут использоваться — в этом случае я использую VehicleModule , который мы создали ранее.  Если вам нужно использовать больше модулей, просто добавьте их, используя запятую в качестве разделителя. 
  В интерфейсе добавьте методы для каждого нужного вам объекта, и он автоматически предоставит вам один со всеми удовлетворенными зависимостями.  В этом случае мне нужен только объект Vehicle , поэтому существует только один метод. 
  Шаг 5: Использование интерфейса @Component для получения объектов 
  Теперь, когда у вас есть все готовые соединения, вы должны получить экземпляр этого интерфейса и вызвать его методы для получения нужного вам объекта.  Я собираюсь реализовать это в методе onCreate в MainActivity следующим образом: 
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package com.androidheroes.tutsplusdagger; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.widget.Toast; import com.androidheroes.tutsplusdagger.component.Dagger_VehicleComponent; import com.androidheroes.tutsplusdagger.component.VehicleComponent; import com.androidheroes.tutsplusdagger.model.Vehicle; import com.androidheroes.tutsplusdagger.module.VehicleModule; public class MainActivity extends ActionBarActivity {     Vehicle vehicle;     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         VehicleComponent component = Dagger_VehicleComponent.builder().vehicleModule(new VehicleModule()).build();         vehicle = component.provideVehicle();         Toast.makeText(this, String.valueOf(vehicle.getSpeed()), Toast.LENGTH_SHORT).show();     } } | 
  Когда вы пытаетесь создать новый объект интерфейса с аннотацией @Component , вы должны сделать это с помощью префикса Dagger_<NameOfTheComponentInterface> , в данном случае Dagger_VehicleComponent , а затем использовать метод builder для вызова каждого модуля внутри. 
  Вы можете видеть, что магия происходит в строке 23. Вы запрашиваете только один объект класса Vehicle    и библиотека отвечает за удовлетворение всех зависимостей, в которых нуждается этот объект.  Опять же, вы можете видеть, что нет никакого нового экземпляра любого другого объекта — все управляется библиотекой. 
  Теперь вы можете запустить приложение и попробовать его на своем устройстве или в эмуляторе.  Если вы пошагово выполняли урок, вы увидите сообщение Toast указанием начального значения или переменной rpm . 
  В прикрепленном проекте вы можете увидеть пользовательский интерфейс для класса MainActivity , в котором вы можете изменять значение переменной rpm , нажимая кнопки на экране. 
Вывод
Внедрение зависимостей — это шаблон, который вам рано или поздно придется внедрить в ваши собственные приложения. С Dagger 2 у вас есть простая в использовании библиотека для его реализации. Я надеюсь, что вы нашли этот урок полезным, и не забудьте поделиться им, если он вам понравился.
Отличный способ стать разработчиком для Android — это использовать шаблоны приложений Android для запуска своих проектов. Вы можете найти шаблоны для игр или других приложений, отдельные элементы пользовательского интерфейса и многое другое.
Или, если вы хотите, чтобы что-то полностью соответствовало вашим спецификациям, вы можете нанять разработчика Android для Envato Studio, чтобы сделать что угодно, от настроек и исправлений ошибок до создания целого приложения с нуля.
