Wie kann ich Dagger 2 mitteilen, welche Implementierung basierend auf X instanziiert werden soll?

Wenn ich innerhalb eines Moduls eine andere Implementierung einer Schnittstelle basierend auf einer zur Modulkonstruktionszeit bekannten Variablen bereitstellen muss, kann ich die Logik in die @Provides-Methode für diesen Schnittstellentyp einfügen. Wie so:

@Module
public class FooModule {

    private final State state;

    public FooModule(State state) {
        this.state = state;
    }

    @Provides
    FooInterface provideFooImplementation() {
        switch(state) {
            case STATE_1:
                return new FooImpl1();
            case STATE_2:
                return new FooImpl2();
            ...
            case STATE_10:
                return new FooImpl10();
        }
    }
}

Diese Implementierungen könnten jedoch von Dagger erstellt werden. Ich würde eher sagen "Hey, basierend auf X möchte ich, dass du diese Klasse für mich instanziierst"

ch habe ein paar Optionen in Betracht gezoge

Ändern Sie die Methode offers, um alle möglichen Implementierungen zu berücksichtigen:

@Provides
FooInterface provideFooImplementation(FooImpl1 impl1, FooImpl2 imp2, ..., FooImpl10 impl10) {
    switch(state) {
        case STATE_1:
            return impl1;
        case STATE_2:
            return impl2;
        ...
        case STATE_10:
            return impl10;
    }
}

Auf diese Weise kann Dagger sie instanziieren und alle ihre Abhängigkeiten erfüllen. Es ist jedoch keine gute Idee, wenn die Implementierung relativ umfangreich oder teuer ist.

Ändern Sie die Methode offers, um eine Sammlung aller Abhängigkeiten für die verschiedenen Implementierungen aufzunehmen.

@Provides
FooInterface provideFooImplementation(Context context, Repo repo, HttpClient httpClient, ...) {
    switch(state) {
        case STATE_1:
            return new FooImpl1(context);
        case STATE_2:
            return new FooImpl2(repo, httpClient);
        ...
        case STATE_10:
            return new FooImpl10(context, repo);
    }
}

Dies ist etwas besser als Option 1, da Dagger nicht jede einzelne Implementierung instanziieren muss, aber dennoch alle Abhängigkeiten instanziieren muss, auch wenn sie möglicherweise nicht in allen Fällen verwendet werden. Ich kehre auch zurück, um die Objekte selbst zu erstellen, obwohl sie von Dagger erstellt werden könnten.

Erstellen Sie ein Modul pro Implementierung und instanziieren Sie das entsprechende Modul. Also so etwas wie:

@Module
public FooImpl1Module {

    @Provides
    FooInterface provideFooImplementation(Context context) {
        return new FooImpl1(context);
    }
}

Das wäre in Ordnung, aber jetzt habe ich Probleme beim Definieren der Komponente, die vom Modul abhängt.

Was ist der beste Weg, um dieses Problem anzugehen?

Ein Vorschlag war, Option 1 mit den in Lazy eingeschlossenen Parametern zu versuchen. Dann rufe ich am Ende nur noch .get () auf. Ich werde das ausprobieren, wenn ich kann und die Ergebnisse posten

Antworten auf die Frage(6)

Ihre Antwort auf die Frage