Dagger2: So verwenden Sie @Provides und @Binds im selben Modul
Lesezeit: 4 Minuten
Ich verwende den neuen Dagger2 (Version 2.11) und nutze die neuen Funktionen wie AndroidInjectorUnd ContributesAndroidInjector. Ich habe eine Aktivitätsunterkomponente,
@Module
abstract class ActivityBuilderModule {
@ContributesAndroidInjector(modules =
{UserListModule.class, MainFragmentModule.class})
@ActivityScope
abstract MainActivity bindsMainActivity();
}
@Module
public abstract class MainFragmentModule {
@ContributesAndroidInjector
@FragmentScope
@FragmentKey(UserListFragment.class)
abstract UserListFragment bindsUserListFragment();
}
Und das UserListModule stellt Abhängigkeiten für das Fragment bereit. Bei einigen Abhängigkeiten möchte ich nur die Instanzen binden und zurückgeben, z
Mein Modul enthält einige @Provides auch Methoden. Können wir beides nutzen? @Binds Und @Provides Methoden im selben Modul? Ich habe es wie unten gezeigt versucht
@Module
public abstract class UserListModule {
@Provides
@ActivityScope
UserListFragment mUserListFragment() {
return new UserListFragment();
}
@Binds
@ActivityScope
abstract UserListView mUserListView(UserListFragment userListFragment);
// other provides and binds methods...
......
.....
}
Und es ist ein Wurffehler
Error:(22, 8) error: dagger.internal.codegen.ComponentProcessor was unable to process this interface because not all of its dependencies could be resolved. Check for compilation errors or a circular dependency with generated code.
Gibt es eine Möglichkeit, dies zu tun?
Ihnen ist doch klar, dass Fragmente, die Sie dem Fragmentmanager hinzufügen, vom System neu erstellt werden und sich nach dem Prozessabbruch wahrscheinlich nicht mehr im Modul befinden, oder?
– EpicPandaForce
7. Oktober 2017 um 9:47 Uhr
Du meintest, ich solle das Fragment nicht untersuchen? Könnten Sie das bitte klarer formulieren? Ich habe dich nicht richtig verstanden
– Benutzer4260260
7. Okt. 2017 um 9:51
Nach einem Prozesstod wird das Fragment vom System und nicht von diesem Modul initialisiert. Sie werden also wahrscheinlich zwei Instanzen davon haben.
– EpicPandaForce
7. Okt. 2017 um 9:58
Okay, aber was ist mit der eigentlichen Frage? Können wir sowohl die Binds- als auch die Provides-Methode im selben Modul verwenden?
– Benutzer4260260
7. Okt. 2017 um 10:06
Ich finde @Binds + @Provides sollte funktionieren, aber ich weiß nicht wie ContributesAndroidInjector beeinflusst es.
– EpicPandaForce
7. Okt. 2017 um 10:08
@Binds Und @ContributesAndroidInjector Methoden müssen abstrakt sein, da sie keine Methodenkörper haben. Das bedeutet, dass sie sich auf einer Schnittstelle oder einer abstrakten Klasse befinden müssen. @Provides Methoden können sein staticwas bedeutet, dass sie auf abstrakten Klassen und Java-8-kompilierten Schnittstellen basieren können, jedoch nicht statisch („Instanz“) @Provides Methoden funktionieren nicht für abstrakte Klassen. Dies ist in den Dagger-FAQ unter den Abschnitten explizit aufgeführt „Warum nicht? @Binds und Instanz @Provides Methoden gehen in dasselbe Modul?“ Und „Was mache ich stattdessen?“.
Wenn dein @Provides Da die Methode keinen Instanzstatus verwendet, können Sie sie markieren staticund es kann in eine abstrakte Klasse neben Ihrer gehen @Binds Methoden. Wenn nicht, erwägen Sie, die Bindungen wie folgt anzubringen @Binds Und @ContributesAndroidInjector in eine separate Klasse – möglicherweise eine statisch verschachtelte Klasse – und diese mithilfe von einschließen includes Attribut auf Dagger’s @Module Anmerkung.
Eine kleine Ergänzung zu Jeffs obiger Lösung:
Sie können eine innere Schnittstelle anstelle einer statischen inneren Klasse erstellen, wie folgt:
@Module(includes = AppModule.BindsModule.class)
public class AppModule {
// usual non-static @Provides
@Provides
@Singleton
Checkout provideCheckout(Billing billing, Products products) {
return Checkout.forApplication(billing, products);
}
// interface with @Binds
@Module
public interface BindsModule {
@Binds
ISettings bindSettings(Settings settings);
}
}
Gibt es neben dem Entfernen des Schlüsselwort-Boilerplates „abstrakt“ einen Vor-/Nachteil bei der Verwendung einer Schnittstelle anstelle einer abstrakten Klasse?
– Paul T.
6. Juni 2019 um 9:05 Uhr
Gibt es neben dem Entfernen des Schlüsselwort-Boilerplates „abstrakt“ einen Vor-/Nachteil bei der Verwendung einer Schnittstelle anstelle einer abstrakten Klasse?
Dies ist eine Lösung anderer Art: Fügen Sie Module zu anderen Modulen hinzu, danach können Sie das Top-Modul in Ihrer Komponentenschnittstelle aufrufen. Es kann effizienter sein, weil Sie abstrakte und statische Methoden verwenden können.
Details und Beispiele finden Sie unten:
Wir haben zum Beispiel eine Komponentenschnittstelle und zwei Module wie Komponentenklassen, Module_ClassA Und Module_ClassB.
Module_ClassA Ist:
@Module
public class Module_ClassA {
@Provides
static ClassA provideClassA(){
return new ClassA();
}
}
Jetzt haben wir also zwei Modelle. Wenn Sie sie zusammen verwenden möchten, können Sie sie miteinander kombinieren. Zum Beispiel: Sie können hinzufügen Module_ClassB Zu Module_ClassA:
@Module(includes = Module_ClassB.class)
public class Module_ClassA {
@Provides
static ClassA provideClassA(){
return new ClassA();
}
}
Schließlich müssen Sie nicht beide Module zu Ihrer Komponentenklasse hinzufügen. Sie können Ihr oberstes Modul nur wie folgt zu Ihrer Komponentenklasse hinzufügen:
Ihnen ist doch klar, dass Fragmente, die Sie dem Fragmentmanager hinzufügen, vom System neu erstellt werden und sich nach dem Prozessabbruch wahrscheinlich nicht mehr im Modul befinden, oder?
– EpicPandaForce
7. Oktober 2017 um 9:47 Uhr
Du meintest, ich solle das Fragment nicht untersuchen? Könnten Sie das bitte klarer formulieren? Ich habe dich nicht richtig verstanden
– Benutzer4260260
7. Okt. 2017 um 9:51
Nach einem Prozesstod wird das Fragment vom System und nicht von diesem Modul initialisiert. Sie werden also wahrscheinlich zwei Instanzen davon haben.
– EpicPandaForce
7. Okt. 2017 um 9:58
Okay, aber was ist mit der eigentlichen Frage? Können wir sowohl die Binds- als auch die Provides-Methode im selben Modul verwenden?
– Benutzer4260260
7. Okt. 2017 um 10:06
Ich finde
@Binds
+@Provides
sollte funktionieren, aber ich weiß nicht wieContributesAndroidInjector
beeinflusst es.– EpicPandaForce
7. Okt. 2017 um 10:08