J'ai posté une question ( Dagger 2 ne génère pas la classe de composants (Android, Kotlin) ), et après quelques expériences, il semble que le problème pourrait être dû au fait que Kotlin cache le champ.
class CoffeeShop {
@Inject
var theCoffee: Coffee? = null
}
Le message d'erreur est,
:app:kaptDebugKotline: ...\CoffeeShop.Java:7:
error: Dagger does not support injection into private fields
e: private ....Coffee theCoffee;
theCoffee
n'était pas privé dans mon code source. Mais je pense que Kotlin peut traduire
class CoffeeShop {
@Inject
var theCoffee: Coffee? = null
}
dans Java code de
class CoffeeShop {
@Inject
private Coffee theCoffee = null;
public Coffee getTheCoffee();
public void setTheCoffee();
}
Puis-je utiliser l'injection de terrain dans Kotlin?
Je pense que Kotlin peut traduire [...] en Java code de [...]
Et vous auriez raison, c'est exactement ce qui se passe.
En général, dans Kotlin, vous n'écrivez pas
@Inject var coffee: Coffee? = null
car lorsque vous allez accéder au café, il ne sera jamais nul. En d'autres termes, vous injecterez toujours l'objet avant d'accéder à ses champs. Cela fait que les opérateurs !!
redondant et ?
inutile. Kotlin a le modificateur de propriété lateinit
pour exprimer cela.
@Inject lateinit var coffee: Coffee
Lorsque vous utilisez lateinit
, le champ généré a la même visibilité que son getter et son setter, dans ce cas public
. Cela le fait fonctionner avec Dagger.
Vous pouvez voir le résultat en affichant le bytecode Kotlin généré.
Menu principal> Outils> Kotlin> Afficher le bytecode Kotlin
Cependant, une approche encore meilleure consisterait à injecter le constructeur de classe:
class CoffeeShop @Inject constructor(val coffee: Coffee) {
//...
}
Dans ce cas, coffee
n'est pas var
et ne peut pas être réaffecté.
L'injection de constructeur n'est pas une option lorsque l'instance est créée pour vous par un framework, l'activité Android est un bon exemple.
Remarque: Lorsque vous utilisez des qualificatifs, vous devez spécifier field
cible d'annotation sur eux:
@Inject @field:Named("Arabica") @field:Arabica
lateinit var coffee: Coffee
Puis-je utiliser l'injection de terrain dans Kotlin?
Oui, vous pouvez. Comme expliqué ci-dessus, l'injection de champs est en fait appliquée pour les propriétés lateinit
.
Mais vous étiez probablement intéressé par la génération et l'injection de champs sans getter/setter dans Kotlin.
@JvmField @Inject
var coffee: Coffee? = null