Содержание

  1. Введение
  2. Что такое Dependency Injection, Пример зависимости
  3. Dagger 2 – введение
  4. Первое использование Dagger 2

Введение


Статья написана не продвинутым программистом для таких же, обычными и понятными словами
В статье используется пример кода на Kotlin. Версия dagger 2.17. Пример можно скачать в конце статьи.

Что такое Dependency Injection


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

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

class Car(private var engine: Engine)

class Engine ( private var fuel: Fuel)

class Fuel(){
private val fuel = if(BuildConfig.DEBUG){
	“benzine”
} else {
	“diesel”
}
}

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

Dagger 2 – введение


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

Плюсы dagger:

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

Минусы dagger:

  • Отсутствие подробной документации
  • Dagger пытается понять намерения разработчика при помощи аннотаций. Это усложняется когда он вас не правильно понимает
  • dagger генерирует код, ошибки в которых так же сложно определить

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


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

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

apply plugin: 'kotlin-kapt'

1.2 в разделе dependencies

{
...
    kapt "com.google.dagger:dagger-compiler:$dagger_version"
    implementation "com.google.dagger:dagger:$dagger_version"
} 

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

ext {
    dagger_version = '2.17'
}

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

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

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

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


class Car constructor(private var engine: Engine)

class Engine constructor(private var fuel: Fuel)

class Fuel {
    private val fuelType = if(BuildConfig.DEBUG){
        "benzine"
    }else{
        "diesel"
    }
}

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

class Car @Inject constructor(private var engine: Engine)
class Engine @Inject constructor(private var fuel: Fuel)
class Fuel @Inject constructor() {
    private val fuelType = if(BuildConfig.DEBUG){
        "benzine"
    }else{
        "diesel"
    }
}

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

Выглядит это так:


@Component
interface DaggerComponent {
    fun getCar(): Car
    fun getEngine(): Engine
    fun getFuel(): Fuel
}

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

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

// Generated by Dagger (https://google.github.io/dagger).
package com.example.dagger2;

public final class DaggerDaggerComponent implements DaggerComponent {
  private DaggerDaggerComponent(Builder builder) {}

  public static Builder builder() {
    return new Builder();
  }

  public static DaggerComponent create() {
    return new Builder().build();
  }

  @Override
  public Car getCar() {
    return new Car(getEngine());
  }

  @Override
  public Engine getEngine() {
    return new Engine(new Fuel());
  }
  @Override
  public Fuel getFuel() {
    return new Fuel();
  }

  public static final class Builder {
    private Builder() {}

    public DaggerComponent build() {
      return new DaggerDaggerComponent(this);
    }
  }
}

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

private var car: Car = DaggerDaggerComponent.create().getCar()

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

Исходник

Комментарии (2)


  1. abbath0767
    10.09.2019 10:47

    Позвольте добавить замечание в 1001 статью про даггер.
    В плюсы наверное стоит добавить одно из его приемуществ перед другими фреймворками — компайлтайм есепшны. Вы упадете если что то не так в 95% случаев до того как все будет собрано.
    В минусы так же стоит добавить рядом с кодогенерацией время. В крупных проектах это действительно становится проблемой


    1. Frank82 Автор
      13.09.2019 11:36

      Спасибо за заметки. Статья написано в 1001 скорее для себя, чтоб упорядочить и закрепить свои поняти по теме.

      Спасибо что подсказали проблемы про скорость сборки с dagger, не знал