我发布了一个问题(Dagger 2 does not generate the component class (Android, Kotlin)),经过一些实验,似乎问题可能是因为Kotlin隐藏了该字段。
<html>
<head>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<link rel="stylesheet" href="css/style.css">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="header">
<div class=header-text">100+ Years Of Combiend Expierence</div>
<div class="header-logo"></div>
</div>
</body>
</html>
错误消息是,
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;
在我的源代码中不是私有的。但我认为Kotlin可能正在翻译
theCoffee
到
的Java代码中class CoffeeShop {
@Inject
var theCoffee: Coffee? = null
}
我可以在Kotlin中使用现场注射吗?
答案 0 :(得分:33)
我认为Kotlin可能正在将[...]翻译成[...]
的Java代码
你会是正确的,这恰恰发生了什么。
通常在Kotlin你不会写
@Inject var coffee: Coffee? = null
因为当您要访问咖啡时,它永远不会为空。换句话说,在访问对象之前,您将始终注入对象。这使得运营商!!
变得多余,?
不必要。 Kotlin有lateinit
属性修饰符来表达这一点。
@Inject lateinit var coffee: Coffee
使用lateinit
时,生成的字段与其getter和setter具有相同的可见性,在本例中为public
。这使它适用于Dagger。
您可以通过查看生成的Kotlin字节码来查看结果。
主菜单&gt;工具&gt; Kotlin&gt;显示Kotlin Bytecode
然而,更好的方法是注入类构造函数:
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