Внедрение зависимостей — это шаблон проектирования программного обеспечения, направленный на то, чтобы сделать наши приложения слабосвязанными, расширяемыми и обслуживаемыми. Из этого руководства вы узнаете, как обрабатывать внедрение зависимостей с помощью 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, чтобы сделать что угодно, от настроек и исправлений ошибок до создания целого приложения с нуля.