我可以在Kotlin中使用Dagger 2的现场注射吗?

我发布了一个问题( Dagger 2不会生成组件类(Android,Kotlin) ),经过一些实验,似乎问题可能是由于Kotlin隐藏了该字段。

class CoffeeShop { @Inject var TheCoffee:Coffee? = null; } 

错误信息是,

 :app:kaptDebugKotline: ...\CoffeeShop.java:7: error: Dagger does not support injection into private fields e: private ....Coffee TheCoffee; 

TheCoffee在我的源代码中不是私有的。 但我认为Kotlin可能会翻译

 class CoffeeShop { @Inject var TheCoffee:Coffee? = null; } 

转换成Java代码

 class CoffeeShop { @Inject private Coffee TheCoffee = null; public Coffee getTheCoffee(); public void setTheCoffee(); } 

我可以在Kotlin中使用现场注射吗?

我认为Kotlin可能会翻译成[…] Java代码,

你会是正确的,这正是发生的事情。

通常在Kotlin你不会写

 @Inject var coffee: Coffee? = null 

因为当你要访问咖啡时,它永远不会是空的。 换句话说,在访问它的字段之前,你总会注入对象。 这使得操作员!! 多余的? 不必要。 Kotlin有lateinit属性修饰符来表达这一点。

 @Inject lateinit var coffee: Coffee 

在使用lateinit ,生成的字段与其getter和setter具有相同的可见性,在本例中为public 。 这使得它与匕首合作。

您可以通过查看生成的Kotlin字节码来查看结果。

主菜单>工具> Kotlin>显示Kotlin字节码

然而,更好的方法是注入类的构造函数:

 class CoffeeShop @Inject constructor(val coffee: Coffee) { //... } 

在这种情况下, coffee不是var ,不能被重新分配。

当框架为您创建实例时,注入构造函数不是一个选项,Android活动就是一个很好的例子。


注意:使用限定符时,您必须在其上指定field注释目标:

 @Inject @field:Named("Arabica") @field:Arabica lateinit var coffee: Coffee 

我可以在Kotlin中使用现场注射吗?

是的你可以。 如上所解释的,实际上对于lateinit特性应用场注入。

但是我们可能有兴趣在Kotlin中没有getter / setter的情况下生成和注入字段。

 @JvmField @Inject var coffee: Coffee? = null