Инъекция зависимостей Dagger2: Как это работает в приложении для Android? - PullRequest
0 голосов
/ 16 июня 2019

Я пытаюсь понять пример для приложения с автономной поддержкой с использованием дооснащения и комнаты:

Вы можете найти код для этого здесь :

В этом проекте используются инъекции зависимостей с помощью Dagger2. Я никогда не работал с этим, поэтому я пытаюсь понять, как все работает вместе. Я понимаю цель внедрения зависимости, но не понимаю реализацию проекта выше.

Я нашел очень хорошее введение в Dagger2 здесь:

Знакомство с Кинжалом 2

Пример кинжала 2 Код :

Я прошел через это и получил большую часть. Вернуться к реальному проекту, который я пытаюсь понять (ссылка 2). Это все еще не имеет смысла для меня, и вот почему:

  1. Интерфейс AppComponent имеет один метод, который используется: public void inject(MainActivity2ViewModel viewModelModule); Тип возврата void. В примере проекта Dagger2 (ссылки 3 и 4) они используют WeatherReporter getWeatherReporter();, что имеет смысл, потому что позже они вызывают этот метод для получения WeatherReporter-Instance, а Dagger2 управляет всем процессом создания экземпляров в фоновом режиме. Но я ничего не получаю, если возвращаемый тип void. Почему тип возвращаемого значения не является объектом?

  2. В MainActivity2ViewModel есть один @Inject:

    @ Inject public void setRepository (GitHubRepository2 репозиторий) { this.repository = хранилище; }

repository - единственное поле MainActivity2ViewModel, поэтому оно является зависимостью. Конструктор GitHubRepository2 имеет 3 параметра:

    @Inject
    public GitHubRepository2(GitHubApi api, GitHubDao dao, Executor executor)

Для каждого из них есть модуль, объясняющий, как создавать эти объекты. Но почему существуют AppModule и NetModule? Может быть, там есть AppModule, потому что DaoModule нужна ссылка на приложение, но почему существует NetModule и где он используется?

1 Ответ

1 голос
/ 17 июня 2019

Существует множество подробных руководств по Dagger2 в Android.Но я покажу вам, для чего он используется.И минимальное использование.

В конечном счете, кинжал будет использовать аннотацию @Inject, которая будет предоставлять (ссылку на объект или значение) на переменную.

Инъекция обычно используется на объектах многократного использования или шаблонных объектах, таких какДао, Репозиторий, ViewModel, NetworkAdapter

class SomethingThatRequiresNetwork { // Activity, Fragment
    @Inject
    MyReusableNetworkAdapter myReusableNetworkAdapter;

    String baseUrl; // for example purpose only
    SomeDependency someDependency;

    void init() {
        // @NOTE: DaggerMyExampleComponent is a generated class. It will be red before compilation.
        MyExampleComponent MyExampleComponent = DaggerMyExampleComponent.builder().build();
        MyExampleComponent.inject(this); // the actual injection happens here
    }

    // yes, you can just use @Inject on the variables directly but this is another use.
    @Inject
    void methodInjection(String baseUrl, SomeDependency someDependency) {
        this.baseUrl = baseUrl;
        this.someDependency = someDependency;
    }
}

// ANSWER to the two questions
// this is a pseudocode of the generated code. You do not write this
// MyExampleComponent class
void inject(SomethingThatRequiresNetwork obj) {
    // @NOTE: modules are actually instantiated by MyExampleComponent. Not called statically. I just shortened it
    obj.myReusableNetworkAdapter = NetModule.provideNetworkAdapter();
    obj.methodInjection(NetModule.provideBaseUrl(), SomeModule.provideSomeDependency());
}
// these here are modules that provide by return TYPE
// you write these

@Module
class NetModule {
    @Provides
    @Singleton
    String provideBaseUrl() {
        return "www.some-url.com";
    }

    @Provides
    @Singleton // will store the object and reuse it.
    // @NOTE: provision can work internally within modules or inter-module. the input here is provided by provideBaseUrl
    MyReusableNetworkAdapter provideNetworkAdapter(String baseUrl) {
        return new MyReusableNetworkAdapter(baseUrl);
    }

}

@Modules
class SomeModule {
    @Provides
    @Singleton
    SomeDependency provideSomeDependency() {
        return new SomeDependency();
    }
}
// Component. uses modules

@Singleton // .build() will reuse
@Component(modules = {NetModule.class, SomeModule.class})
interface MyExampleComponent {
    // the method name doesn't matter
    // the class type does matter though.
    void inject(SomethingThatRequiresNetwork somethingThatRequiresNetwork);

    // some other class that needs injection. @NOTE: I did not give example for this
    void inject(SomethingThatRequiresDependency some); 

}

ПРИМЕЧАНИЕ.Этот код обычно пишется снизу вверх.Вы начинаете писать «Компонент», затем «Модуль», а затем «Инъекции».

Просто следуйте указаниям в верхней части этого ответа, и вы поймете, как работает Dagger2.

...