Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
After spending a ludicrous amount of time trying to figure out why my dagger injections weren't working; I realised that the "object" type in Kotlin was the problem.
The following did not work, the injected "property" was null.
object SomeSingleton {
@Inject
lateinit var property: Property
init {
DaggerGraphController.inject(this)
However, the following DID work just fine:
class NotSingleton {
@Inject
lateinit var property: Property
init {
DaggerGraphController.inject(this)
I tried google, I tried the documentation but I could not pin point the reason behind this. Also note that I havent tried this with JAVA, JAVA doesnt have the concept of singletons built in anyway.
Why is this the case? Why is a kotlin singleton unable to inject members but a regular non-singleton class can?
–
If you look into kotlin bytecode you'll find that the code you've written is translated into following:
public final class SomeSingleton {
public static LProperty; property // <- Notice static field here
public final getProperty()LProperty
public final setProperty(LProperty)V
As you can see the actual field is static which makes it uneligible for instance injection. You may try to move @Inject
annotation onto setter method by doing so:
object SomeSingleton {
@set:Inject
lateinit var property: Property
–
–
A workaround for this can be to extend a BaseClass that consists of the fields to be injected.
object SomeSingleton : BaseClass {
open class BaseClass{
@Inject
lateinit var property: Property
init{
YourDaggerComponent.inject(this)
This does work, although this would leak this
, which comes up as an android studio warning, to get rid of that make the Base class abstract and instead inject the fields in your original object class
object SomeSingleton : BaseClass {
// Add the init block here instead of the base class
init{
YourDaggerComponent.inject(this)
abstract class BaseClass{
@Inject
lateinit var property: Property
//Remove the init block from here
And you Dagger AppComponent interface can be like, any of those function def should work
interface Component{
fun inject(someSingleton : SomeSingleton)
fun inject(baseClass: BaseClass)
I hope this helps....
–
–
This was previously allowed by a bug in Dagger. As others described, it is because the properties in a kotlin object are backed by static fields.
See https://github.com/google/dagger/issues/1665 for the fix. It was fixed in 2.27.
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.