Зачем дважды вводить приложение 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поля и методы. Это корень графа зависимостей.

Технически, компонентный метод может вызываться столько раз, сколько вам нужно, а метод построения может быть вызван только один раз.

Другие вопросы по тегам