Dolchinjektion funktioniert nicht für "Objekt" in Kotlin - android - Program QA

Dolchinjektion funktioniert nicht für "Objekt" in Kotlin

2018-01-24 android kotlin singleton dagger

Nachdem ich eine lächerliche Zeit damit verbracht hatte herauszufinden, warum meine Dolchinjektionen nicht funktionierten; Mir wurde klar, dass der "Objekt" -Typ in Kotlin das Problem war.

Das Folgende hat nicht funktioniert, die injizierte "Eigenschaft" war null.

object SomeSingleton {

    @Inject
    lateinit var property: Property

    init {
        DaggerGraphController.inject(this)
    }
}

Die folgenden DIDs funktionierten jedoch einwandfrei:

class NotSingleton {

    @Inject
    lateinit var property: Property

    init {
        DaggerGraphController.inject(this)
    }
}

Ich habe Google ausprobiert, ich habe die Dokumentation ausprobiert, aber ich konnte den Grund dafür nicht genau bestimmen. Beachten Sie auch, dass ich dies nicht mit JAVA versucht habe. JAVA hat sowieso nicht das Konzept von Singletons eingebaut.

Warum ist das so? Warum kann ein Kotlin-Singleton keine Mitglieder injizieren, eine reguläre Nicht-Singleton-Klasse jedoch?

Answers

Wenn Sie sich den Kotlin-Bytecode ansehen, werden Sie feststellen, dass der von Ihnen geschriebene Code in Folgendes übersetzt wurde:

public final class SomeSingleton {
    public static LProperty; property // <- Notice static field here

    public final getProperty()LProperty
    ...

    public final setProperty(LProperty)V
    ...
}

Wie Sie sehen können, ist das tatsächliche Feld statisch, was es beispielsweise für die Injektion nicht geeignet macht. Sie können versuchen, die @Inject Annotation auf die Setter-Methode zu verschieben, @Inject Sie @Inject tun:

object SomeSingleton {
    @set:Inject
    lateinit var property: Property
    ...
}

Ich habe versucht, dagger.Lazy<YourClass> zu verwenden. dagger.Lazy<YourClass> und es funktioniert

 @set:Inject
lateinit var authClient: dagger.Lazy<PlatformAuthClient>

Möglicherweise benötigen Sie noch den @Singleton Dekorator über Ihrer Objektdefinition. Dieser Dekorateur macht Ihre Klasse nicht zum "Singleton", sondern wird nur von Dagger verwendet, um alle Abhängigkeiten an derselben Stelle abzurufen.

Eine Problemumgehung hierfür kann darin bestehen, eine BaseClass zu erweitern, die aus den einzufügenden Feldern besteht.

object SomeSingleton : BaseClass {
    ...
    ...
}

open class BaseClass{
    @Inject
    lateinit var property: Property

    init{
        YourDaggerComponent.inject(this)
    }

}

Dies funktioniert, obwohl dies auslaufen würde this , die als Android Studio Warnung kommt, um loszuwerden , dass die Basisklasse abstrakt und stattdessen inject die Felder in Ihrer ursprünglichen Objektklasse machen

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

}

Und Sie Dagger AppComponent-Schnittstelle kann sein, wie jede dieser Funktionen def funktionieren sollte

interface Component{
    fun inject(someSingleton : SomeSingleton)
    //OR
    fun inject(baseClass: BaseClass)
}

Ich hoffe das hilft....

Related