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

Dam*_*les 18 kotlin dagger-2

我发布了一个问题(Dagger 2没有生成组件类(Android,Kotlin)),经过一些实验,似乎问题可能是因为Kotlin隐藏了这个领域.

class CoffeeShop {
    @Inject
    var theCoffee: Coffee? = null
}
Run Code Online (Sandbox Code Playgroud)

错误消息是,

:app:kaptDebugKotline: ...\CoffeeShop.java:7:
error: Dagger does not support injection into private fields
e:     private ....Coffee theCoffee;
Run Code Online (Sandbox Code Playgroud)

theCoffee在我的源代码中不是私有的.但我认为Kotlin可能正在进行翻译

class CoffeeShop {
    @Inject
    var theCoffee: Coffee? = null
}
Run Code Online (Sandbox Code Playgroud)

到Java代码

class CoffeeShop {
    @Inject
    private Coffee theCoffee = null;
    public Coffee getTheCoffee();
    public void setTheCoffee();
}
Run Code Online (Sandbox Code Playgroud)

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

Eug*_*nec 42

我认为Kotlin可能正在将[...]翻译成Java代码[...]

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

通常在Kotlin你不会写

@Inject var coffee: Coffee? = null
Run Code Online (Sandbox Code Playgroud)

因为当你要去咖啡时,它永远不会是空的.换句话说,在访问对象的字段之前,您将始终注入对象.这使得运营商变得!!多余且?不必要.Kotlin有lateinit表达这个的属性修饰符.

@Inject lateinit var coffee: Coffee
Run Code Online (Sandbox Code Playgroud)

lateinit在这种情况下,使用生成的字段与其getter和setter具有相同的可见性public.这使得它与Dagger一起使用.

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

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

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

class CoffeeShop @Inject constructor(val coffee: Coffee) {
    //...
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下coffee,不能var也不能重新分配.

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


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

@Inject @field:Named("Arabica") @field:Arabica
lateinit var coffee: Coffee
Run Code Online (Sandbox Code Playgroud)

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

是的你可以.如上所述,实际注入实际应用于field属性.

但你可能对Kotlin中没有getter/setter的字段生成和注入感兴趣.

@JvmField @Inject
var coffee: Coffee? = null
Run Code Online (Sandbox Code Playgroud)