2016-07-10 10 views
3

Ich möchte inject Interface-Implementierung in abstrakten Klassenkonstruktor und verwenden Sie es in der untergeordneten Klasse.Dolch inject Schnittstelle in der Basisklasse

Ich habe Kompilierung Fehler:

Error:Gradle: Dagger does not support injection into private fields 
Error:Gradle: Example.A cannot be provided without an @Provides-annotated method. 
Error:Gradle: Example.B cannot be provided without an @Inject constructor or from an @Provides-annotated method. 
Error:Gradle: Execution failed for task ':app:compileDemoDebugJavaWithJavac'. 
> Compilation failed; see the compiler error output for details. 

Beispiel in Kotlin.

object Example { 
    interface IData { 

     fun foo() { 
     } 
    } 

    class Data : IData { 

    } 

    @Module 
    class DataModel { 
     @Provides 
     fun data(): IData = Data() 
    } 

    @Singleton 
    @Component(modules = 
    arrayOf(DataModel::class) 
    ) 
    interface Injector { 
     fun inject(a: A) 
     fun inject(b: B) 
    } 

    val graph: Injector = DaggerInjector.builder(). 
      dataModel(DataModel()). 
      build() 

    abstract class A { 

     @Inject var data: IData ? = null 

     public open fun setUp() { 
      graph.inject(this) 
     } 
    } 

    open class B : A() { 

     override fun setUp() { 
      super.setUp() 
      data!!.foo() 
     } 
    } 

    fun bar() { 
     val a = B() 
     a.setUp() 
    } 
} 

Versionen:

  • com.android.tools.build:gradle:2.1.2
  • ext.kotlin_version = '1.0.3'
  • Kompilierung ‚com.google.dagger : dagger: 2,4'
  • bereitgestellt 'org.glassfish: javax.annotation: 10,0-b28'
  • Kapt 'com.google.dagger: dolch Compiler: 2,4'

Hier ist der Fall. Dekompilierten java

public static class A { 
    @Inject 
    @Nullable 
    private Example.IData data; 

    @Nullable 
    protected final Example.IData getData() { 
    return this.data; 
    } 

    protected final void setData(@Nullable Example.IData <set-?>) { 
    this.data = <set-?>; 
    } 

    public void setUp() { 
    Example.INSTANCE.getGraph().inject(this); 
    } 

}

Antwort

7

Von der Fehlermeldung, ich denke, das Problem mit dieser Linie ist:

@Inject var data: IData ? = null 

Das Trägerfeld für diese Eigenschaft ist private, und das ist, was der Fehler sagt. Normalerweise sind die lateinit Schlüsselwort wird für solche Fälle verwendet:

@Inject lateinit var data: IData 

lateinit ist eine von mehreren Modifikatoren, die das dahinter liegende Feld direkt mit der Unterkunft Zugriffsebene (public hier) aussetzen, um es sichtbar zu Dagger-generierten Klassen zu machen.

+0

Danke. Ich konnte nicht verstehen, was vor sich ging. Daten sind geschützt und mutable. – punksta

+0

@StasShakirov der Ausschnitt, den du angehängt hast, wird dekompiliert, nachdem du 'lateritit' angewendet hast, richtig? Wenn Sie mit dem Code vor 'LateInit 'das Gleiche tun, sollten Sie stattdessen diese Zeile' private Example.IData data;' sehen. Und da Dolch keine Setter verwendet, um '@ Inject'-Felder zu füllen, sondern stattdessen versucht, direkt auf das Feld zuzugreifen, wird der Fehler im ursprünglichen Fall ausgegeben. Diese Sichtbarkeitsänderung ist ein Nebeneffekt von 'laterinit' (zusätzlich zu seiner Hauptbedeutung in Kotlin), da dieser Modifikator ursprünglich für die Unterstützung der Abhängigkeitsinjektion erstellt wurde. – AndroidEx

+0

Ich war ein wenig zu spät, um Ihren Kommentar zu beantworten :) Hoffentlich macht es jetzt Sinn. – AndroidEx

Verwandte Themen