Как мне сообщить Dagger 2, какую реализацию создавать на основе X?

Внутри модуля, если мне нужно предоставить другую реализацию интерфейса, основанную на переменной, известной во время создания модуля, я могу поместить логику в метод @Provides для этого типа интерфейса. Вот так:

@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();
        }
    }
}

Тем не менее, эти реализации могут быть созданы Dagger. Я бы скорее сказал: «Эй, основываясь на X, я хочу, чтобы ты создал для меня этот класс»

Я рассмотрел пару вариантов.

Измените метод обеспечивает, чтобы принимать во всех возможных реализациях:

@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;
    }
}

Это позволяет Dagger создавать их экземпляры и удовлетворять все их зависимости, но не очень хорошая идея, если каждая из реализаций является относительно большой или дорогой в создании.

Измените метод предоставляет, чтобы получить коллекцию всех зависимостей для различных реализаций.

@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);
    }
}

Это немного лучше, чем вариант 1 в том смысле, что Dagger не должен создавать экземпляры каждой отдельной реализации, однако ему все еще нужно создавать экземпляры всех зависимостей, даже если они могут использоваться не во всех случаях. Я также вернулся к созданию объектов сам, хотя они могут быть созданы Dagger.

Создайте один модуль для каждой реализации и создайте экземпляр соответствующего модуля. Так что-то вроде:

@Module
public FooImpl1Module {

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

Это было бы хорошо, но теперь у меня есть проблемы с определением компонента, который зависит от модуля.

Какой лучший способ решить эту проблему?

Одним из предложений было попробовать вариант 1 с параметрами, обернутыми в Lazy. Тогда я в итоге вызываю .get () только для одного. Я попробую это когда смогу и опубликую результаты