2016-07-18 28 views
2

Ich habe 2 Komponenten: die AppComponent und die ApiComponent. Ich würde gerne die Abhängigkeiten verwenden, die von der AppComponent in der ApiComponent und in den Objekten zur Verfügung gestellt werden, auf die die ApiComponent injiziert wird. So sehe ich die ApiComponent als Unterkomponente der AppComponent. Ich habe die AppComponent als Abhängigkeit in den ApiComponent erklärt mit der dependecies Richtlinie:Dolch 2 Sub-Komponente Injektion Fehler

@ApiScope 
@Component(dependencies = { AppComponent.class}, 
      modules = { ApiModule.class }) 
public interface ApiComponent { 
    void inject(Application application); 
    void inject(IntentService1 service1); 

    SampleApi sampleApi(); 
} 

Hier mein AppComponent ist:

@Singleton 
@Component (modules = { AppModule.class }) 
public interface AppComponent { 
    void (Class2 class2); 

    Bus bus(); 
    SharedPreferences sharedPreferences(); 
    SampleApplication sampleApplication(); 
} 

Der relevante Teil meiner ApiModule wie folgt aussieht:

@Module 
public final class ApiModule { 
    @Provides 
    @ApiScope 
    SampleApi provideSampleApi(Retrofit retrofit) { 
     return retrofit.create(SampleApi.class);; 
    } 
} 

Ich trigne die Injektion in onCreate() Methode meines IntentService1:

@Inject SampleApi sampleApi; 

@Override 
public void onCreate() { 
    SampleApplication.get().getApiComponent().inject(this); 
} 

Aber ich erhalte den folgenden Compiler-Fehler:

SampleApi cannot be provided without an @Provides or @Produce-annotated method

Hat jemand eine Ahnung, was los ist? Ich schätze Ihre Hilfe.

Antwort

0

Mein Problem war mit Bereichen. Ich habe falsche Anmerkungen zum Deklarieren eines Bereichs verwendet. Dies ist, wie ich einen Umfang erklären jetzt:

@Retention(RetentionPolicy.RUNTIME) 
@Scope 
public @interface ApiScope { 
} 

Es ist ärgerlich, dass eine abhängige Komponente nicht den gleichen Singleton Umfang wie ihre übergeordnete Komponente haben kann, und dass Sie Scopes für alle Ihre Singleton-Komponenten zu erklären, aber die Grund wird here beschrieben. Stellen Sie außerdem sicher, dass ALLE Ihre Provider-Methoden in Ihrem Modul mit dem gleichen Bereich wie dem Bereich Ihrer Komponente kommentiert werden. Hier ist eine meiner Anbieter Methoden:

@Provides 
@ApiScope 
UserApi provideUserApi(Retrofit retrofit) { 
    return retrofit.create(UserApi.class); 
} 

Und stellen Sie sicher, dass Sie explizit die Abhängigkeiten von der übergeordneten Komponente ausgesetzt werden durch Methoden mit dem gleichen Namen wie die Abhängigkeit bieten sie (mit Ausnahme der Kapital den ersten Buchstaben), die beide in der Deklaration Stammkomponente (Schnittstelle) und in der abhängigen Komponente, wie folgt aus:

Bus bus(); 
SharedPreferences sharedPreferences(); 
MyApplication myApplication(); 

auch stellen Sie sicher, um die Abhängigkeiten zu belichten Ihre (abhängigen) Modul in Ihrem (abhängigen) Komponente liefert, wieder den Namen des Belichter Methode sollte identisch sein Name Ihrer Abhängigkeit, mit Ausnahme des ersten Buchstabens:

UserApi userApi(); 

Auch stellen Sie sicher, 2. Dieser Stackoverflow diese sehr nützliche und genaue article auf Dagger überprüfen answer mir geholfen, mein Problem zu erklären, Bereiche zu lokalisieren, und die Abhängigkeiten Lebenszyklus zu verwalten.

PS: Ich vermeide es, den Begriff "Unterkomponente" zu verwenden, da es eine andere Möglichkeit gibt, eine "Unterkomponente" in Dagger 2 zu deklarieren, obwohl abhängige Komponenten und Unterkomponenten konzeptionell identisch sind.

2

Ich bin auch in diesem Fall. Ich glaube, was Sie hier wollen, ist ein @Subcomponent. Ich glaube, dass die Direktive der Abhängigkeiten ist, wenn dein unteres Modul (das das Wort 'sub' aus Gründen der Klarheit vermeidet) nicht über die in deinem 'root' Modul deklarierten Abhängigkeiten weiß (oder wissen willst) (dh das Modul mit Items wie der Event-Bus). Zitieren der Dagger 2 Dokumentation über Komponente dependencies = { };

Component Dependencies

While subcomponents are the simplest way to compose subgraphs of bindings, subcomponents are tightly coupled with the parents; they may use any binding defined by their ancestor component and subcomponents. As an alternative, components can use bindings only from another component interface by declaring a component dependency. When a type is used as a component dependency, each provision method on the dependency is bound as a provider. Note that only the bindings exposed as provision methods are available through component dependencies.

Ich habe versucht, neu zu schreiben Ihren Code zu helfen, aber ich kann nicht sagen, ich verstehe das alles so werde ich Ihnen zeigen, wie ich dieses Konstrukt verwendet habe gerade vor kurzem in meiner App. Hoffe das hilft und du kannst die Parallelen zwischen deinem Fall und diesem ziehen. So

....

Szenario: Mein SplashActivity trägt eine LocalBroadcastManager Abhängigkeit und AktivitätContext auf die grafische Darstellung des Root-Modul und eine Datenbank Abhängigkeit vom Hauptmodul verwendet ... sehr ähnlich wie Ihre Anwendungsfall.

@PerActivity 
@Subcomponent(
    modules = SplashActivityModule.class 
) 
public interface SplashActivityComponent { 
    void inject(final SplashActivity splashActivity); 
} 

Schnipsel 1: Splash Aktivität Subkomponente

@Module 
public class SplashActivityModule { 
    private final Context activity; 

    /** 
    * Constructs the activity module. 
    * 
    * @param activity The activity context. 
    */ 
    public SplashActivityModule(final Activity activity) { 
    this.activity = activity; 
    } 


    /** 
    * Provide the (domain) context. 
    * 
    * @return The context of the domain module. 
    */ 
    @Provides 
    @PerActivity 
    Context provideContext() { 
    return activity; 
    } 


    /** 
    * Provide the local broadcast manager. 
    * 
    * @return the broadcast manager. 
    */ 
    @Provides 
    @PerActivity 
    LocalBroadcastManager provideLocalBroadcastManager() { 
    return LocalBroadcastManager.getInstance(activity); 
    } 
} 

Schnipsel 2: Injektions Anweisungen für die Aktivität auch bekannt als die SplashActivityModule

@Component(modules = DomainModule.class) 
public interface DomainComponent { 
    SplashActivityComponent plus(final SplashActivityModule splashActivityModule); 
} 

Schnipsel 3: Parent (oder Root-) Modul, das ein ent liefert ry-point in das Diagramm.

@Override 
protected void setupActivityComponent(final DomainComponent domainComponent) { 
    domainComponent.plus(new SplashActivityModule(this)).inject(this); 
} 

Snippet 4: SplashActivity Code die Injektion (genannt unmittelbar nach onCreate ‚s Super-Anruf)

Hoffnung zu tun, das hilft. Halten Sie mich über Ihre Ergebnisse auf dem Laufenden, weil ich mit dem Szenario kämpfe, bei dem das Kindmodul nichts über den Elternteil wissen kann ... d. nicht ein @Subcomponent.

+2

Gerade gelöst mein Nicht-Subkomponenten-Problem .... je mehr ich Dolch 2 benutze desto weniger Magie finde ich. Es ist nur Java ... einige davon generiert, einige davon nicht! – OceanLife