Dagger2依赖项注入:它如何在android应用中工作?

时间:2019-06-16 14:53:57

标签: android dependency-injection dagger-2 android-architecture-components

我正在尝试通过改型和空间来了解具有离线支持的应用的example

您可以找到它的代码here

该项目正在Dagger2中使用依赖项注入。我从未使用过它,因此我试图了解它们如何协同工作。我了解依赖项注入的目的,但不了解上述项目的实施。

我在这里找到了Dagger2的很好的介绍:

A Friendly Introduction to Dagger 2

Dagger 2 example Code

我研究了其中的大部分内容。回到我试图理解的实际项目(链接2)。这对我来说仍然没有意义,这就是原因:

  1. AppComponent接口具有一种使用的方法: public void inject(MainActivity2ViewModel viewModelModule);返回类型为void。在Dagger2示例项目(链接3和4)中,他们使用WeatherReporter getWeatherReporter();是有意义的,因为后来他们调用此方法来获取WeatherReporter-Instance,并且Dagger2在后台管理所有实例化过程。但是如果返回类型为空,我什么也没得到。为什么返回类型不是对象?

  2. MainActivity2ViewModel中有一个@Inject

    @注入     公共无效setRepository(GitHubRepository2存储库){         this.repository =储存库;     }

repositoryMainActivity2ViewModel的唯一字段,因此它是一个依赖项。 GitHubRepository2构造函数具有3个参数:

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

每个模块都有一个模块说明如何创建这些对象。但是为什么会有AppModule和NetModule?也许有AppModule,是因为DaoModule需要一个Application引用,但是为什么要有NetModule?在哪里使用它?

1 个答案:

答案 0 :(得分:1)

关于Android中的Dagger2,有很多综合教程。但是,我将向您展示它的用途。而且使用最少。

最终,dagger将使用@Inject注释,它将为变量提供(对对象或值的引用)。

注入通常用于可重用或样板对象,例如Dao,Repository,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的工作原理。