问题描述
我发布了一个问题( Dagger 2没有生成组件类(Android,Kotlin)),经过一些实验,看来问题可能出在Kotlin隐藏该字段.
I posted a question (Dagger 2 does not generate the component class (Android, Kotlin)), and after some experiments, it seems that the problem might be due to that Kotlin hides the field.
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可能正在翻译
theCoffee
was not private in my source code. But I think Kotlin may be translating
class CoffeeShop {
@Inject
var theCoffee: Coffee? = null
}
转换为的Java代码
class CoffeeShop {
@Inject
private Coffee theCoffee = null;
public Coffee getTheCoffee();
public void setTheCoffee();
}
我可以在Kotlin中使用场注入吗?
Can I use field injection in Kotlin?
推荐答案
您是正确的,这就是会发生的事情.
And you would be correct, that's exactly what happens.
在科特林,您通常不会写
Typically in Kotlin you wouldn't write
@Inject var coffee: Coffee? = null
因为要使用咖啡,它永远不会为空.换句话说,您将始终在访问对象的字段之前注入对象.这使得运算符!!
多余,而?
则不必要. Kotlin具有lateinit
属性修饰符来表达这一点.
because when you're going to access coffee, it will never be null. In other words you will always inject the object before accessing it's fields. That makes the operators !!
redundant and ?
unnecessary. Kotlin has lateinit
property modifier to express this.
@Inject lateinit var coffee: Coffee
使用lateinit
时,生成的字段与其getter和setter(在本例中为public
)具有相同的可见性.这使得它可以与Dagger一起使用.
When you use lateinit
the generated field has the same visibility as its getter and setter, in this case public
. This makes it work with Dagger.
您可以通过查看生成的Kotlin字节码来查看结果.
You can see the result by viewing generated Kotlin bytecode.
但是,更好的方法是注入类构造函数:
However, even better approach would be injecting the class constructor:
class CoffeeShop @Inject constructor(val coffee: Coffee) {
//...
}
在这种情况下,coffee
不是var
,因此无法重新分配.
In this case coffee
is not var
and can't be reassigned.
在通过框架为您创建实例时,不能选择注入构造函数,Android活动就是一个很好的例子.
Injecting constructor is not an option when the instance is created for you by a framework, Android activity is a good example.
注意:使用限定符时,必须在其上指定field
注释目标:
Note: When using qualifiers you have to specify field
annotation target on them:
@Inject @field:Named("Arabica") @field:Arabica
lateinit var coffee: Coffee
编辑:使用.
You don't need to add the field
target when using Dagger 2.25 or newer.
是的,可以.如上所述,场注入实际上应用于lateinit
属性.
Yes you can. As explained above, field injection is actually applied for lateinit
properties.
但是您可能对在Kotlin中没有getter/setter的情况下生成和注入字段感兴趣.
But you were probably interested in generating and injecting fields without getter/setter in Kotlin.
@JvmField @Inject
var coffee: Coffee? = null
这篇关于我可以在Kotlin中使用Dagger 2的场注入吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!