在Dagger中,Inject annotated类是否也充当提供者?

时间:2018-05-22 11:34:30

标签: dagger-2 dagger

我是Dagger的新手(Android版本2.16),根据我的阅读情况,据我所知,对于某个组件,应该有一个提供程序(@Provides@Binds)封装在一个模块(@Module)。通过大量的示例,我看到代码中包含一些在任何模块中都没有提供的对象,也没有使用new进行实例化。

我的理解是,为了访问模块中的依赖项,使用者类需要将自己注入到组件图中(组件通常提供一种注入类的方法)。代码示例也没有这样做。

Here's some code展示了我的担忧。 <{3}}未在任何模块中提供,但仍RecipePresenter正在使用它。

我能想到的一个可能的解释是@Inject,除了请求依赖项之外,还将请求类(链接代码中的RecipePresenter)添加/注入到组件图中。但假设有多个组件/子组件,哪个组件使用@Inject构造函数的类是否附加到? 如果我的理解是正确的,为什么活动和片段必须在组件中手动注入 - 如果它们声明一个用@Inject注释的变量,它们是否应该自动注入?

1 个答案:

答案 0 :(得分:1)

RecipePresenter有一个@Inject - 带注释的构造函数,允许它被提供。 RecipeActivity中@Inject字段上的recipePresenter注释没有帮助,只有@Inject - 带注释的构造函数。

class RecipePresenter @Inject constructor(
    private val useCase: RecipeUseCase,
    private val res: StringRetriever) :
    RecipeUseCase.Callback {

From the Dagger User's Guide:

  

使用@Inject注释Dagger应该用来创建类实例的构造函数。当请求新实例时,Dagger将获取所需的参数值并调用此构造函数。

如果带有@Inject注释构造函数的类也具有已定义的scope,则绑定将仅影响具有相同范围注释的组件:@ActivityScope类不会#39;例如,可以从@Singleton组件访问。如果类没有定义范围,那么绑定可以出现在需要它的任何和所有组件上,这很好:实现总是相同的,由构造函数本身定义。

@Inject根据其注释内容有不同的含义:

  • 当您使用@Inject注释某个字段时,它表示DI系统应根据DI系统的值在注入该对象时设置该字段。
  • 当您使用@Inject注释方法时,它表示DI系统应该使用基于DI系统的值的参数调用该方法,当注入该对象时。
  • 使用@Inject注释构造函数时,表示允许DI系统调用该构造函数以创建该对象(触发上面的字段和方法注入) 。从这个意义上讲,它确实像内置的提供商一样。

在Dagger中,@Provides方法优先于@Inject构造函数(如果它们都存在于同一个类中),并且与JSR-330规范不同,Dagger需要@Inject - 即使没有其他构造函数存在,也可以使用带注释的构造函数。来自Dagger用户指南:

  

如果您的班级有@Inject - 带注释的字段但没有@Inject - 带注释的构造函数,Dagger会在请求时注入这些字段,但不会创建新实例。添加带有@Inject注释的无参数构造函数,以指示Dagger也可以创建实例。

     

Dagger无法构建缺少@Inject注释的类。

最后,回答你关于为什么活动和片段需要注入自己的问题:允许Android在没有Dagger帮助或参与的情况下反射性地创建Activity / Fragment / View对象。这意味着没有任何内容触发上述字段和方法注入,直到您调用a members-injection method on the component指示Dagger填充这些字段并调用这些方法。因此,您永远不会在Android中的应用程序,活动,服务,片段,视图,ContentProvider和BroadcastReceiver子类上看到@Inject - 带注释的构造函数:Android将忽略@Inject注释,因此您可能也应该如此自己控制注射,手动或通过dagger.android