Can I use Dagger 2's field injection in Kotlin?
up vote
12
down vote
favorite
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
}
The error message is,
:app:kaptDebugKotline: ...CoffeeShop.java:7:
error: Dagger does not support injection into private fields
e: private ....Coffee theCoffee;
theCoffee
was not private in my source code. But I think Kotlin may be translating
class CoffeeShop {
@Inject
var theCoffee: Coffee? = null
}
into Java code of
class CoffeeShop {
@Inject
private Coffee theCoffee = null;
public Coffee getTheCoffee();
public void setTheCoffee();
}
Can I use field injection in Kotlin?
kotlin dagger-2
add a comment |
up vote
12
down vote
favorite
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
}
The error message is,
:app:kaptDebugKotline: ...CoffeeShop.java:7:
error: Dagger does not support injection into private fields
e: private ....Coffee theCoffee;
theCoffee
was not private in my source code. But I think Kotlin may be translating
class CoffeeShop {
@Inject
var theCoffee: Coffee? = null
}
into Java code of
class CoffeeShop {
@Inject
private Coffee theCoffee = null;
public Coffee getTheCoffee();
public void setTheCoffee();
}
Can I use field injection in Kotlin?
kotlin dagger-2
add a comment |
up vote
12
down vote
favorite
up vote
12
down vote
favorite
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
}
The error message is,
:app:kaptDebugKotline: ...CoffeeShop.java:7:
error: Dagger does not support injection into private fields
e: private ....Coffee theCoffee;
theCoffee
was not private in my source code. But I think Kotlin may be translating
class CoffeeShop {
@Inject
var theCoffee: Coffee? = null
}
into Java code of
class CoffeeShop {
@Inject
private Coffee theCoffee = null;
public Coffee getTheCoffee();
public void setTheCoffee();
}
Can I use field injection in Kotlin?
kotlin dagger-2
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
}
The error message is,
:app:kaptDebugKotline: ...CoffeeShop.java:7:
error: Dagger does not support injection into private fields
e: private ....Coffee theCoffee;
theCoffee
was not private in my source code. But I think Kotlin may be translating
class CoffeeShop {
@Inject
var theCoffee: Coffee? = null
}
into Java code of
class CoffeeShop {
@Inject
private Coffee theCoffee = null;
public Coffee getTheCoffee();
public void setTheCoffee();
}
Can I use field injection in Kotlin?
kotlin dagger-2
kotlin dagger-2
edited Nov 22 at 15:38
William Reed
762818
762818
asked Nov 12 '17 at 11:53
Damn Vegetables
2,27722244
2,27722244
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
27
down vote
accepted
I think Kotlin may be translating [...] into Java code of [...]
And you would be correct, that's exactly what happens.
Typically in Kotlin you wouldn't write
@Inject var coffee: Coffee? = null
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
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.
You can see the result by viewing generated Kotlin bytecode.
Main menu > Tools > Kotlin > Show Kotlin Bytecode
However, even better approach would be injecting the class constructor:
class CoffeeShop @Inject constructor(val coffee: Coffee) {
//...
}
In this case coffee
is not var
and can't be reassigned.
Injecting constructor is not an option when the instance is created for you by a framework, Android activity is a good example.
Note: When using qualifiers you have to specify field
annotation target on them:
@Inject @field:Named("Arabica") @field:Arabica
lateinit var coffee: Coffee
Can I use field injection in Kotlin?
Yes you can. As explained above, field injection is actually applied for lateinit
properties.
But you were probably interested in generating and injecting fields without getter/setter in Kotlin.
@JvmField @Inject
var coffee: Coffee? = null
Actually I sawlateinit
before posting this question, but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection, is that correct? The error message wasCoffee cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
. So, doesn't that make the answer to my question a "no"?
– Damn Vegetables
Nov 12 '17 at 12:26
@DamnVegetables Damn, I completely missed the question :D Check out the updated answer.but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection
Now I'm not sure what you mean byfield injection
. CallingMembersInjector
manually? That works with lateinit. lateinit=field as far as dagger is concerned.
– Eugen Pechanec
Nov 12 '17 at 13:05
Thank you. If you do not mind, where doesArabica
came from? And the error message,@Provides- or @Produces-annotated method
, does that mean a provide/produces forCoffeeShop
? Because a provide method forCoffee
already exists. (The full source is in the question I mentioned.)
– Damn Vegetables
Nov 12 '17 at 13:36
@DamnVegetablesArabica
is a made up custom qualifier. You probably won't need qualifiers just now. Focus on getting it to work. About the error: Dagger needs to injectval coffee: Coffee
and for that it needs to know whereCoffee
comes from. As the error hints there are two ways. The user guide explains it best, I think.
– Eugen Pechanec
Nov 12 '17 at 13:47
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
27
down vote
accepted
I think Kotlin may be translating [...] into Java code of [...]
And you would be correct, that's exactly what happens.
Typically in Kotlin you wouldn't write
@Inject var coffee: Coffee? = null
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
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.
You can see the result by viewing generated Kotlin bytecode.
Main menu > Tools > Kotlin > Show Kotlin Bytecode
However, even better approach would be injecting the class constructor:
class CoffeeShop @Inject constructor(val coffee: Coffee) {
//...
}
In this case coffee
is not var
and can't be reassigned.
Injecting constructor is not an option when the instance is created for you by a framework, Android activity is a good example.
Note: When using qualifiers you have to specify field
annotation target on them:
@Inject @field:Named("Arabica") @field:Arabica
lateinit var coffee: Coffee
Can I use field injection in Kotlin?
Yes you can. As explained above, field injection is actually applied for lateinit
properties.
But you were probably interested in generating and injecting fields without getter/setter in Kotlin.
@JvmField @Inject
var coffee: Coffee? = null
Actually I sawlateinit
before posting this question, but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection, is that correct? The error message wasCoffee cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
. So, doesn't that make the answer to my question a "no"?
– Damn Vegetables
Nov 12 '17 at 12:26
@DamnVegetables Damn, I completely missed the question :D Check out the updated answer.but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection
Now I'm not sure what you mean byfield injection
. CallingMembersInjector
manually? That works with lateinit. lateinit=field as far as dagger is concerned.
– Eugen Pechanec
Nov 12 '17 at 13:05
Thank you. If you do not mind, where doesArabica
came from? And the error message,@Provides- or @Produces-annotated method
, does that mean a provide/produces forCoffeeShop
? Because a provide method forCoffee
already exists. (The full source is in the question I mentioned.)
– Damn Vegetables
Nov 12 '17 at 13:36
@DamnVegetablesArabica
is a made up custom qualifier. You probably won't need qualifiers just now. Focus on getting it to work. About the error: Dagger needs to injectval coffee: Coffee
and for that it needs to know whereCoffee
comes from. As the error hints there are two ways. The user guide explains it best, I think.
– Eugen Pechanec
Nov 12 '17 at 13:47
add a comment |
up vote
27
down vote
accepted
I think Kotlin may be translating [...] into Java code of [...]
And you would be correct, that's exactly what happens.
Typically in Kotlin you wouldn't write
@Inject var coffee: Coffee? = null
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
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.
You can see the result by viewing generated Kotlin bytecode.
Main menu > Tools > Kotlin > Show Kotlin Bytecode
However, even better approach would be injecting the class constructor:
class CoffeeShop @Inject constructor(val coffee: Coffee) {
//...
}
In this case coffee
is not var
and can't be reassigned.
Injecting constructor is not an option when the instance is created for you by a framework, Android activity is a good example.
Note: When using qualifiers you have to specify field
annotation target on them:
@Inject @field:Named("Arabica") @field:Arabica
lateinit var coffee: Coffee
Can I use field injection in Kotlin?
Yes you can. As explained above, field injection is actually applied for lateinit
properties.
But you were probably interested in generating and injecting fields without getter/setter in Kotlin.
@JvmField @Inject
var coffee: Coffee? = null
Actually I sawlateinit
before posting this question, but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection, is that correct? The error message wasCoffee cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
. So, doesn't that make the answer to my question a "no"?
– Damn Vegetables
Nov 12 '17 at 12:26
@DamnVegetables Damn, I completely missed the question :D Check out the updated answer.but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection
Now I'm not sure what you mean byfield injection
. CallingMembersInjector
manually? That works with lateinit. lateinit=field as far as dagger is concerned.
– Eugen Pechanec
Nov 12 '17 at 13:05
Thank you. If you do not mind, where doesArabica
came from? And the error message,@Provides- or @Produces-annotated method
, does that mean a provide/produces forCoffeeShop
? Because a provide method forCoffee
already exists. (The full source is in the question I mentioned.)
– Damn Vegetables
Nov 12 '17 at 13:36
@DamnVegetablesArabica
is a made up custom qualifier. You probably won't need qualifiers just now. Focus on getting it to work. About the error: Dagger needs to injectval coffee: Coffee
and for that it needs to know whereCoffee
comes from. As the error hints there are two ways. The user guide explains it best, I think.
– Eugen Pechanec
Nov 12 '17 at 13:47
add a comment |
up vote
27
down vote
accepted
up vote
27
down vote
accepted
I think Kotlin may be translating [...] into Java code of [...]
And you would be correct, that's exactly what happens.
Typically in Kotlin you wouldn't write
@Inject var coffee: Coffee? = null
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
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.
You can see the result by viewing generated Kotlin bytecode.
Main menu > Tools > Kotlin > Show Kotlin Bytecode
However, even better approach would be injecting the class constructor:
class CoffeeShop @Inject constructor(val coffee: Coffee) {
//...
}
In this case coffee
is not var
and can't be reassigned.
Injecting constructor is not an option when the instance is created for you by a framework, Android activity is a good example.
Note: When using qualifiers you have to specify field
annotation target on them:
@Inject @field:Named("Arabica") @field:Arabica
lateinit var coffee: Coffee
Can I use field injection in Kotlin?
Yes you can. As explained above, field injection is actually applied for lateinit
properties.
But you were probably interested in generating and injecting fields without getter/setter in Kotlin.
@JvmField @Inject
var coffee: Coffee? = null
I think Kotlin may be translating [...] into Java code of [...]
And you would be correct, that's exactly what happens.
Typically in Kotlin you wouldn't write
@Inject var coffee: Coffee? = null
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
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.
You can see the result by viewing generated Kotlin bytecode.
Main menu > Tools > Kotlin > Show Kotlin Bytecode
However, even better approach would be injecting the class constructor:
class CoffeeShop @Inject constructor(val coffee: Coffee) {
//...
}
In this case coffee
is not var
and can't be reassigned.
Injecting constructor is not an option when the instance is created for you by a framework, Android activity is a good example.
Note: When using qualifiers you have to specify field
annotation target on them:
@Inject @field:Named("Arabica") @field:Arabica
lateinit var coffee: Coffee
Can I use field injection in Kotlin?
Yes you can. As explained above, field injection is actually applied for lateinit
properties.
But you were probably interested in generating and injecting fields without getter/setter in Kotlin.
@JvmField @Inject
var coffee: Coffee? = null
edited Jan 16 at 11:09
answered Nov 12 '17 at 12:15
Eugen Pechanec
26.1k76889
26.1k76889
Actually I sawlateinit
before posting this question, but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection, is that correct? The error message wasCoffee cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
. So, doesn't that make the answer to my question a "no"?
– Damn Vegetables
Nov 12 '17 at 12:26
@DamnVegetables Damn, I completely missed the question :D Check out the updated answer.but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection
Now I'm not sure what you mean byfield injection
. CallingMembersInjector
manually? That works with lateinit. lateinit=field as far as dagger is concerned.
– Eugen Pechanec
Nov 12 '17 at 13:05
Thank you. If you do not mind, where doesArabica
came from? And the error message,@Provides- or @Produces-annotated method
, does that mean a provide/produces forCoffeeShop
? Because a provide method forCoffee
already exists. (The full source is in the question I mentioned.)
– Damn Vegetables
Nov 12 '17 at 13:36
@DamnVegetablesArabica
is a made up custom qualifier. You probably won't need qualifiers just now. Focus on getting it to work. About the error: Dagger needs to injectval coffee: Coffee
and for that it needs to know whereCoffee
comes from. As the error hints there are two ways. The user guide explains it best, I think.
– Eugen Pechanec
Nov 12 '17 at 13:47
add a comment |
Actually I sawlateinit
before posting this question, but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection, is that correct? The error message wasCoffee cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
. So, doesn't that make the answer to my question a "no"?
– Damn Vegetables
Nov 12 '17 at 12:26
@DamnVegetables Damn, I completely missed the question :D Check out the updated answer.but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection
Now I'm not sure what you mean byfield injection
. CallingMembersInjector
manually? That works with lateinit. lateinit=field as far as dagger is concerned.
– Eugen Pechanec
Nov 12 '17 at 13:05
Thank you. If you do not mind, where doesArabica
came from? And the error message,@Provides- or @Produces-annotated method
, does that mean a provide/produces forCoffeeShop
? Because a provide method forCoffee
already exists. (The full source is in the question I mentioned.)
– Damn Vegetables
Nov 12 '17 at 13:36
@DamnVegetablesArabica
is a made up custom qualifier. You probably won't need qualifiers just now. Focus on getting it to work. About the error: Dagger needs to injectval coffee: Coffee
and for that it needs to know whereCoffee
comes from. As the error hints there are two ways. The user guide explains it best, I think.
– Eugen Pechanec
Nov 12 '17 at 13:47
Actually I saw
lateinit
before posting this question, but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection, is that correct? The error message was Coffee cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
. So, doesn't that make the answer to my question a "no"?– Damn Vegetables
Nov 12 '17 at 12:26
Actually I saw
lateinit
before posting this question, but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection, is that correct? The error message was Coffee cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
. So, doesn't that make the answer to my question a "no"?– Damn Vegetables
Nov 12 '17 at 12:26
@DamnVegetables Damn, I completely missed the question :D Check out the updated answer.
but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection
Now I'm not sure what you mean by field injection
. Calling MembersInjector
manually? That works with lateinit. lateinit=field as far as dagger is concerned.– Eugen Pechanec
Nov 12 '17 at 13:05
@DamnVegetables Damn, I completely missed the question :D Check out the updated answer.
but if I use 'lateinit', it seemed that I could no longer use field injection but had to use constructor injection
Now I'm not sure what you mean by field injection
. Calling MembersInjector
manually? That works with lateinit. lateinit=field as far as dagger is concerned.– Eugen Pechanec
Nov 12 '17 at 13:05
Thank you. If you do not mind, where does
Arabica
came from? And the error message, @Provides- or @Produces-annotated method
, does that mean a provide/produces for CoffeeShop
? Because a provide method for Coffee
already exists. (The full source is in the question I mentioned.)– Damn Vegetables
Nov 12 '17 at 13:36
Thank you. If you do not mind, where does
Arabica
came from? And the error message, @Provides- or @Produces-annotated method
, does that mean a provide/produces for CoffeeShop
? Because a provide method for Coffee
already exists. (The full source is in the question I mentioned.)– Damn Vegetables
Nov 12 '17 at 13:36
@DamnVegetables
Arabica
is a made up custom qualifier. You probably won't need qualifiers just now. Focus on getting it to work. About the error: Dagger needs to inject val coffee: Coffee
and for that it needs to know where Coffee
comes from. As the error hints there are two ways. The user guide explains it best, I think.– Eugen Pechanec
Nov 12 '17 at 13:47
@DamnVegetables
Arabica
is a made up custom qualifier. You probably won't need qualifiers just now. Focus on getting it to work. About the error: Dagger needs to inject val coffee: Coffee
and for that it needs to know where Coffee
comes from. As the error hints there are two ways. The user guide explains it best, I think.– Eugen Pechanec
Nov 12 '17 at 13:47
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f47248478%2fcan-i-use-dagger-2s-field-injection-in-kotlin%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown