Зачем дважды вводить приложение Android в Dagger?
Глядя на исходный код для примера GithubBrowerSample компонентов архитектуры Android, я не понимаю смысла двойного введения githubApp
,
Не было бы inject
метод будет достаточно? Зачем это нужно им обоим в одном предложении?
public interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance Builder application(Application application);
AppComponent build();
}
void inject(GithubApp githubApp);
}
И они используют это как:
public static void init(GithubApp githubApp) {
DaggerAppComponent.builder().application(githubApp)
.build().inject(githubApp);
2 ответа
Как описал Томас Бройер, у вас есть два отдельных направления: вы хотите, чтобы граф Даггера знал, как добраться до вашего экземпляра приложения, и вы хотите получить доступ к определенным привязкам из графа зависимостей.
@BindsInstance
строка в Builder создает привязку для Application, установленную для экземпляра, который вы передаете. Похоже, вы понимаете эту часть.
Тем не менее, после того, как вы создали свой компонент, по-видимому, вы хотите его использовать. Допустим, вы хотите получить полностью внедренные экземпляры классов Dep1, Dep2 и Dep3 из вашего графика. Один из способов сделать это - создать в компоненте методы, которые получают экземпляры:
@Singleton @Component(/* ... */) interface AppComponent {
// [builder snipped out here]
fun getDep1(): Dep1
fun getDep2(): Dep2
fun getDep3(): Dep3
}
И затем вы называете их как часть создания вашего приложения.
var appComponent = DaggerAppComponent.builder().application(githubApp).build()
var dep1 = appComponent.getDep1()
var dep2 = appComponent.getDep2()
var dep3 = appComponent.getDep3()
// Use dep1, dep2, and dep3 here.
Тем не менее, вы также можете создать метод с одним аргументом, который обычно void
метод называется inject
, Это заполняет все @Inject
-аннотированные поля и вызывает все @Inject
-аннотированные методы в экземпляре, который вы передаете. Если GitHubApp имеет @Inject
-аннотированные поля ( и это делает), вызов inject
позволяет вам пропустить определение всех методов получения в Компоненте. Это уменьшает весь приведенный выше код до:
DaggerAppComponent.builder().application(githubApp)
.build().inject(githubApp)
... что вы видите в демоверсии.
@BindsInstance
говорит Dagger, что он должен внедрить приложение в зависимости от того, @Inject Application
он находит в графе зависимостей.
Вторая просит, чтобы Dagger ввел зависимости в это @Inject
поля и методы. Это корень графа зависимостей.
Технически, компонентный метод может вызываться столько раз, сколько вам нужно, а метод построения может быть вызван только один раз.