Как я внедрял Dagger2 в своём Android приложении
Данная заметка не претендует на какой-то “правильный” мануал о том как использовать Dagger2.
В своё время я уже успел поработать с различными IoC-контейнерами и фреймворками на различных языках и типах проектов, от игр до серверных приложений. Внедрение и первоначальная настройка Dagger 2 мне не показалась такой уж тривиальной и очевидной.
Я потратил несколько часов, чтобы разобраться в том, как это сделать правильно. Предлагаю вам ознакомиться с моими результатами и сэкономить немного времени.
Gradle
Для начала в Gradle добавляем зависимости.
dependencies {
...
implementation 'com.google.dagger:dagger:2.29'
annotationProcessor 'com.google.dagger:dagger-compiler:2.29'
...
}
Версия библиотеки последняя на момент написания заметки.
Создание обслуживающих структур
Далее я завел в папке Dagger2 (создана мною) набор файлов.
AppComponent.java имеет методы, через которые инициализируется внедрение зависимостей в Activity. Метод inject будет вызывается на необходимой Activity, которой требуется dependency injection.
@Singleton
@Component(modules = {ManagersProvides.class, InterfacesProvides.class})
public interface AppComponent {
void inject(PreloaderActivity activity);
void inject(MainActivity activity);
}
p.s. может быть, есть более унифицированное решение, чтобы не плодить методы inject на каждую Activity. Мне пока его найти не удалось.
В Component(modules=…) перечисляются модули, в которых определены методы создания экземпляров классов. Они будут инжектированы.
В модуле InterfaceProvides.java я перечисляю конкретные интерфейсы и их реализации.
@Module
public class InterfacesProvides {
@Provides
public Converters provideConverters() {
return new ImplConverters();
}
}
В модуле ManagersProvides.java я перечисляю менеджеры, которые используются у меня в проекте. Они могут иметь, а могут не иметь интерфейсы.
@Module
public class ManagersProvides {
@Singleton
@Provides
public SettingsManager provideSettingsManager(DataManager dataManager) {
return new ImplSettingsManager(dataManager);
}
@Singleton
@Provides
public DataManager provideDataManager() {
return new DataManager();
}
@Singleton
@Provides
public SessionManager provideSessionManager(SettingsManager settingsManager, DataManager dataManager) {
return new SessionManager(settingsManager, dataManager);
}
}
Если в менеджере есть зависимость от других компонентов, которые должны быть в них инжектированы, они передаются в конструктор.
Такое разбиение на модули исключительно моё решение. У вас может быть своё.
Реализация AppComponent для инициализации инжектирования
В базовом классе для Application необходимо реализовать доступ к AppComponent, чтобы через него вызывать инициализацию инжектирования.
public final class CoinsBook extends Application {
public static AppComponent appComponent = DaggerAppComponent.create();...}
Внедрение зависимостей в Activity и ViewModel’s
На этом этапе проект готов к тому, чтобы использовать Dagger2. Теперь заинжектируем ViewModel в Activity. А потом и мои менеджеры (определенные выше) в ViewModel.
public class MainActivity extends NavigateActivity {
@Inject
protected MainActivityViewModel viewModel; ... public MainActivity() {
} ... @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CoinsBook.appComponent.inject(this); ... }}
Внимание, Dagger2 не умеет инжектировать в private переменные.
public class MainActivityViewModel extends BaseObservable {
protected final DataManager dataManager;
protected final SettingsManager settingsManager;
protected final CurrencyManager currencyManager;
protected final Converters converters;;
@Inject
public MainActivityViewModel(DataManager dataManager,
SettingsManager settingsManager,
CurrencyManager currencyManager, Converters converters) { this.dataManager = dataManager;
this.settingsManager = settingsManager;
this.currencyManager = currencyManager;
this.converters = converters;
} ...}
Обратите внимание, чтобы инжектировать в класс не являющийся Activity, конструктор помечается атрибутом @Inject, и в него передаются все необходимые зависимости (экземпляр зависимости будет создан Dagger2).
В случае с классом Activity этим атрибутом помечается только переменная, которую нужно инжектировать.
Итог
В заметке была показана первоначальная стройка Dagger2 и инжектирование нескольких модулей и классов.
Coins Book в Google Play и группа ВК. Присоединяйтесь!