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

Dagger2 dependency injection: How does it work in an android app?

我正在尝试了解 example 一个应用程序,该应用程序具有使用改造和空间的离线支持:

你可以找到它的代码here:

这个项目正在使用 Dagger2 的依赖注入。我从未使用过它,所以我试图了解它们是如何协同工作的。我理解依赖注入的目的,但是我不理解上面项目的实现。

我在这里找到了关于 Dagger2 的非常好的介绍:

A Friendly Introduction to Dagger 2

Dagger 2 example Code:

我完成了它并掌握了大部分内容。回到我试图理解的实际项目 (link 2)。这对我来说仍然没有意义,原因如下:

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

  2. MainActivity2ViewModel中有一个@Inject

    @注入 public void setRepository(GitHubRepository2 存储库){ this.repository = 存储库; }

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

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

对于它们中的每一个,都有一个模块解释如何创建这些对象。但是为什么会有 AppModule 和 NetModule 呢?也许 AppModule 在那里是因为 DaoModule 需要一个 Application 引用,但为什么有 NetModule 以及它在哪里使用?

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); 

}

注意。这段代码通常是从下往上写的 lol。您开始编写组件,然后是模块,然后是注入。

只需按照此答案顶部的调用,您就会了解 Dagger2 的工作原理。