Dagger 2注入构造函数 [英] Dagger 2 Injecting Constructors

查看:81
本文介绍了Dagger 2注入构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始在我正在开发的应用程序中使用Dagger 2,但我对Dagger 2的工作原理有一些疑问。

I'm starting to use Dagger 2 in an application I'm developing but I have some questions about how Dagger 2 works.

我得到了所有的逻辑在@Provides方法和@Inject注释之后初始化你的依赖关系,但@Inject注释到类构造函数有点像我的想法。

I get the all the logic behind the @Provides methods and the @Inject annotation for initialising your dependencies, but the @Inject annotation to class constructors kind of bugs my mind.

例如:

我的应用程序,我有一个模块定义,ContextModule,用于检索我的应用程序的上下文:

Im my app, I have one module defined, the ContextModule, to retrieve the context of my application:

ContextModule。 java

ContextModule.java

@Module
public class ContextModule {

    private final Context context;

    public ContextModule(Context context) {
        this.context = context;
    }

    @Provides
    public Context context() {
        return this.context;
    }
}

我的BaseActivityComponent使用此模块:

This module is used by my BaseActivityComponent:

BaseActivityComponent.java

BaseActivityComponent.java

@BaseActivityScope
@Component(modules = ContextModule.class)
public interface BaseActivityComponent {
    void injectBaseActivity(BaseActivity baseActivity);
}

到目前为止很好..然后我有一个AuthController类,这取决于上下文,我想在我的BaseActivity中注入它。所以在我的AuthControllers.class中我有类似的东西:

So far so good.. then I have an AuthController class, that depends on the context and I want to inject it in my BaseActivity. So in my AuthControllers.class I have something like:

public class AuthController {

    private Context context;

    @Inject
    public AuthController(Context context) {
        this.context = context;
    }

    public void auth() {
        // DO STUFF WITH CONTEXT
    }
}

我将其注入我的BaseActivity中,如:

And I inject it in my BaseActivity like:

public class BaseActivity extends AppCompatActivity {

    @Inject
    AuthController authController;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        BaseActivityComponent component = DaggerBaseActivityComponent.builder()
            .contextModule(new ContextModule(this))
            .build();

        component.injectBaseActivity(this);

        authController.auth();

    }
}

现在我的问题是,怎么做dagger知道我的AuthControllers是BaseActivity的依赖吗?只需声明

Now my question is, how does dagger knows that my AuthControllers is a dependency for BaseActivity? Just by declaring

@Inject
AuthController authController;

就像我创建一个类似于以下的ControllerModule一样:

it's like the same thing as if I created a ControllerModule like:

@Module(includes = ContextModule.class)
public class ControllerModule {

    @Provides
    AuthController authController(Context context) {
        return new AuthController(context);
    }

}

然后在我的BaseActivityComponent中我会添加我的AuthController getter并将我的依赖模块更改为ControllersModule:

And then in my BaseActivityComponent I would add my AuthController getter and change my dependency module to ControllersModule:

@BaseActivityScope
@Component(modules = ControllersModule.class)
public interface BaseActivityComponent {

    void injectBaseActivity(BaseActivity baseActivity);

    AuthController getAuthController();
}

当我调用injectBaseActivity(this)时,它告诉匕首所有@Inject注释是我的类的依赖,然后它搜索我的项目@Inject注释构造函数匹配该类型?

When I call injectBaseActivity(this) it "tells" dagger that all @Inject annotations are dependencies of my class, and then it searchers my project for @Inject annotated constructors that matches that type?

我认为关于Dagger 2的好处是模块文件可以用作我的依赖项三的文档。但是如果只是在我控制的所有构造函数中添加@Inject,将来不会有点混乱,因为你不知道实际上取决于什么? (我的意思是,你知道什么取决于什么,你只需要浏览很多文件才能真正找到答案)

I thought a good thing about Dagger 2 is that the Module files could be used as a "documentation" of my dependencies three. But if just add @Inject in all the constructors I have control of, couldn't it get a little confusing in the future, since you don't know what actually depends on what? (I mean, you know what depends on what, you just have to browse a lot of files to really find out)

使用@Inject时是否有任何最佳实践构造函数中的注释或何时在Modules文件中添加@Provides方法?
我在构造函数中使用@Inject得到了我不需要更改模块文件中的构造函数定义,但是有任何缺点吗?

Is there any best practices for when using @Inject annotations in constructors or when to add the @Provides method in Modules files? I get that using @Inject in constructor I don't need to change the constructor definition in my Module file, but is there any downside?

谢谢。

推荐答案


当我调用injectBaseActivity(this)时,它告诉匕首所有@Inject注释都是我的类的依赖关系,然后它在我的项目中搜索匹配该类型的@Inject注释构造函数?

When I call injectBaseActivity(this) it "tells" dagger that all @Inject annotations are dependencies of my class, and then it searches my project for @Inject annotated constructors that matches that type?

完全正确。但是当你调用 injectBaseActivity 时它没有完成,但这一切都发生在编译期间。这是注释处理的一种方式(另一种方法是在运行时使用反射)。

Exactly. But it's not done when you call injectBaseActivity, but it all happens during compile time. This is one way of annotation processing (another makes use of reflection at runtime).

当您构建项目时,dagger-annotation-processor在build.gradle文件中包含(作为依赖项),使用 @Inject 注释注释的所有字段,类等的列表进行调用,并构建依赖关系图用它。然后它解析图形,生成源代码,为图表上的项目提供所有依赖项。

When you build your project the dagger-annotation-processor you include (as a dependency)in your build.gradle file gets called with a list of all your fields, classes, etc annotated by the @Inject annotation and builds a dependency graph with it. It then resolves the graph, generating source code that provides all the dependencies for the items on the graph.

injectBaseActivity 只执行之前生成的代码,并将所有依赖项分配给您的对象。它是正确的源代码,您可以阅读和调试。

injectBaseActivity just executes the code which was generated before, and assigns all the dependencies to your object. It is proper source code, which you can read, and debug.

这是编译步骤的原因—简单地说—是性能和验证。 (例如,如果你有一些依赖循环,你得到一个编译错误)

The reason this is a compile step—simply put—is performance and validation. (e.g. If you have some dependency cycle, you get a compile error)


怎么办dagger知道我的AuthControllers是BaseActivity的依赖吗?

how does dagger knows that my AuthControllers is a dependency for BaseActivity?



@Inject
AuthController authController;

通过注释字段 @Inject dagger知道你想要一个 AuthController 。到现在为止还挺好。现在,dagger将寻找一些方法来提供控制器,在组件内查找它,组件依赖项和组件模块。它还将查看该类是否可以自己提供,因为它知道有关其构造函数。

By annotating the field @Inject dagger knows you want an AuthController. So far so good. Now dagger will look for some means to provide the controller, looking for it within the component, the components dependencies, and the components modules. It will also look whether the class can be supplied on its own, because it knows about its constructor.

dagger如何知道对象构造函数,如果你不在任何模块中包含它?

How does dagger know about the objects constructor if you don't include it in any module?

@Inject
public AuthController(Context context) { /**/ }

通过注入构造函数注释你也告诉dagger有一个名为<的类code> AuthController ,你需要一个上下文来实例化它。它与将其添加到模块基本相同。

By annotating the constructor with inject you also told dagger that there is a class called AuthController and you need a context for it to be instantiated. It is basically the same as adding it to your module.

如果您使用模块 @Provides 方法没有源代码只是将 @Inject 注释添加到构造函数中,或者对象是否需要进一步初始化。或者在你的情况下......

A module @Provides method should be used if you don't have the source code to just add the @Inject annotation to the constructor, or if the object needs further initialization. Or in your case...


[...]模块文件可以用作我的依赖树的文档[ ...]

[...]the Module files could be used as a "documentation" of my dependencies tree [...]

是的,当然你可以这样做。但随着项目的增长,你将不得不维护很多不必要的代码,因为在构造函数上使用简单的注释也可以做到这一点。

Yes, of course you could do that. But as your project grows you will have to maintain a lot of unnecessary code, since the same could have been done with a simple annotation on the constructor.


在构造函数中使用@Inject注释或何时在模块文件中添加@Provides方法时是否有最佳实践?

Is there any best practices for when using @Inject annotations in constructors or when to add the @Provides method in Modules files?

如果你想为不同的上下文提供不同的版本(例如以两种不同的方式实现一个接口),还有 @Binds 注释告诉dagger你希望提供哪个类作为实现。

If you want to provide different versions for a different context (e.g. implementing an interface in 2 different ways) there is also the @Binds annotation that tells dagger which class you wish to provide as implementation.

除此之外我认为你应该尽可能使用构造函数注入。如果发生了变化,您不必触及代码的任何其他部分,并且只需要编写更少的代码,因此可以减少包含错误的地方。

Other than that I believe you should always use constructor injection when possible. If something changes you don't have to touch any other parts of your code, and it is just less code that you write, and hence less places where you could include a bug.

Dagger也可以并且通过了解更多来优化很多,如果你实现不必要的代码,它将不得不使用你引入的开销

Also Dagger can and does optimize a lot by knowing more, and if you implement unnecessary code it will have to work with the overhead you introduced

当然最终完全取决于你认为最好的。毕竟必须使用你的代码;)

Of course in the end it is all up to what you think is best. After all it is you that has to work with your code ;)

这篇关于Dagger 2注入构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆