使用Dagger 2注入ViewModel并试图了解为什么@Binds不起作用,而@Provides起作用

时间:2018-10-19 15:04:19

标签: android dependency-injection dagger-2

我正在尝试注入ViewModelProvider.Factory,但无法理解为什么我无法使用@Binds注释。

此注释似乎有效:

(4,1)

结合以下注释,项目可以编译:

@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory viewModelFactory);

但是,如果将上面的代码替换为以下代码:

@Provides
@IntoMap
@ViewModelKey(MyViewModel.class)
static ViewModel MyViewModel(){
    return new MyViewModel();
}

突然我收到以下错误消息:

  

...如果没有@Inject构造函数或   @提供注释的方法。

有人可以解释为什么第一种情况有效而第二种无效吗?据我了解,@ Binds应该创建一个返回类型的类,该类是作为参数传递的具体实现的。

1 个答案:

答案 0 :(得分:1)

正如评论中讨论的egoldx一样,如果希望Dagger调用MyViewModel构造函数,则需要用@Inject进行注释。如您所述,这意味着JSR-330将@Inject定义为具有multiple valid uses

  • 要标记DI系统应调用以获得其实例的构造函数,
  • 要标记DI系统在创建后并在现有实例上应填充的字段,并且
  • 要标记要在创建/注入时调用的方法,请在DI系统中填充其方法参数。

在这里要特别说明的是,匕首的行为documented in the User's Guide

  

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

...与JSR-330's definition of @Inject矛盾,因为公共无参数构造函数不符合被调用的条件:

  

@Inject对于没有参数的公共,无参数构造函数是可选的。这使注入程序可以调用默认构造函数。

围绕这种偏差的讨论在Square's Dagger 1 repository, issue #412Google's Dagger 2 issue #1105中进行。总而言之,额外的清晰度被认为是有用的(特别是考虑到您可能会意外地使用默认构造函数注入的对象数量),添加@Inject的额外成本被确定为不会太繁琐,并且避免了某些歧义。子类是否有资格注入,而不必检查@Inject字段的整个类层次结构。