Dagger2 Ошибка при внедрении в классе, который вводит - PullRequest
0 голосов
/ 20 июня 2019

Я пытаюсь inject в моем presenter и interactor, но выдает мне ошибку, кажется, я не могу ввести в классе, который вводит в другой:

error: [Dagger/DuplicateBindings] com.example.calculadora.Data.Interactor.Operacion is bound multiple times:
@Provides com.example.calculadora.Data.Interactor.Operacion com.example.calculadora.Inject.InteractorModule.provideDiv()
@Provides com.example.calculadora.Data.Interactor.Operacion com.example.calculadora.Inject.InteractorModule.provideMult()
@Provides com.example.calculadora.Data.Interactor.Operacion com.example.calculadora.Inject.InteractorModule.provideResta()
@Provides com.example.calculadora.Data.Interactor.Operacion com.example.calculadora.Inject.InteractorModule.provideSuma()
com.example.calculadora.Data.Interactor.Operacion is injected at
com.example.calculadora.Domain.PresenterImpl.operacion
com.example.calculadora.Domain.PresenterImpl is injected at
com.example.calculadora.Inject.InteractorComponent.inject(com.example.calculadora.Domain.PresenterImpl)

Это мой InteractorModule, который предоставляет мне 4 класса в зависимости от того, что я хочу использовать, и где, кажется, проблема:

@Module
public class InteractorModule {
    @Provides
    public Operacion provideSuma() {
        return new InteractorSuma();
    }

    @Provides
    public Operacion provideResta() {
        return new InteractorResta();
    }

    @Provides
    public Operacion provideDiv() {
        return new InteractorDivision();
    }

    @Provides
    public Operacion provideMult() {
        return new InteractorMultiplicacion();
    }
}

Я хочу добавить сюда вместо init новые элементы:

@Override
public void setCalculo() {
    Operacion operacion = null;
    String[] operandos = vista.getOperandos();
    Operando operando1 = new Operando(Integer.parseInt(operandos[0]));
    Operando operando2 = new Operando(Integer.parseInt(operandos[1]));


    switch (tipoOperacion) {
        case SUMA:
            operacion = new InteractorSuma(operando1, operando2);
            break;
        case RESTA:
            operacion = new InteractorResta(operando1, operando2);
            break;
        case MULT:
            operacion = new InteractorMultiplicacion(operando1, operando2);
            break;
        case DIV:
            operacion = new InteractorDivision(operando1, operando2);
            break;
    }

    operacion.calcular();
    vista.mostrarResultado(String.valueOf(operacion.getResultado().getValor()));
}

Ответы [ 4 ]

2 голосов
/ 20 июня 2019

Для такого рода ситуаций используется Dagger2 Qualifiers.

1.- Создайте свои классификаторы:

@Qualifier
public @interface OperacionSuma {}
@Qualifier
public @interface OperacionResta {}
@Qualifier
public @interface OperacionDiv {}
@Qualifier
public @interface OperacionMult {}

2.- Установите квалификаторы в методах ваших провайдеров:

@Module
public class InteractorModule {
    @Provides
    @OperacionSuma
    public Operacion provideSuma() {
        return new InteractorSuma();
    }

    @Provides
    @OperacionResta
    public Operacion provideResta() {
        return new InteractorResta();
    }

    @Provides
    @OperacionDiv
    public Operacion provideDiv() {
        return new InteractorDivision();
    }

    @Provides
    @OperacionMult
    public Operacion provideMult() {
        return new InteractorMultiplicacion();
    }
} 

3.- Укажите, какую «операцию» вы хотите внедрить в докладчике:

class Presenter {

    @Inject
    Presenter(@OperacionSuma Operacion operacion) { }

    @Inject
    Presenter(@OperacionResta Operacion operacion) { }

    @Inject
    Presenter(@OperacionDiv Operacion operacion) { }

    @Inject
    Presenter(@OperacionMult Operacion operacion) { }
}
1 голос
/ 20 июня 2019

Поскольку кинжал ищет тип возвращаемого значения, а не имя, данное функции, вы должны позаботиться об этом. Тем не менее, Dagger2 предоставляет решение таких проблем. Использование аннотации @Named.

Иногда одного типа недостаточно для определения зависимости. Например, если вам нужен экземпляр Refrofit с GsonConverterFactory и еще один ScalarConverterFactory, вы в конечном итоге получите 2 метода с одинаковым типом возврата: Retrofit. В этом случае вы можете использовать аннотацию @Named для различения двух экземпляров Retrofit

enter image description here

Теперь вы можете использовать его следующим образом

enter image description here

Подходя к вашему делу

@Module
public class InteractorModule {
    @Provides
    @Named("InteractorSuma")
    public Operacion provideSuma() {
        return new InteractorSuma();
    }

    @Provides
    @Named("InteractorResta")
    public Operacion provideResta() {
        return new InteractorResta();
    }

    @Provides
    @Named("InteractorDivision")
    public Operacion provideDiv() {
        return new InteractorDivision();
    }

    @Provides
    @Named("InteractorMultiplicacion")
    public Operacion provideMult() {
        return new InteractorMultiplicacion();
    }
}

Вот полный пример использования @Named аннотации

Дайте мне знать, если у вас все еще есть проблема

1 голос
/ 20 июня 2019

Вы должны отделить друг друга с помощью аннотации @Named("someName"), или вы можете просто сделать то, что говорит @Derek. Мой подход:

@Provides
@Named("someName1")
    public Operacion provideSuma() {
        return new InteractorSuma();
    }

    @Provides
    @Named("someName2")
    public Operacion provideResta() {
        return new InteractorResta();
    }

    @Provides
    @Named("someName3")
    public Operacion provideDiv() {
        return new InteractorDivision();
    }

    @Provides
    @Named("someName4")
    public Operacion provideMult() {
        return new InteractorMultiplicacion();
    }

В противном случае кинжал не знает, куда и куда возвращать.

Позвоните на @Named при инъекции.

0 голосов
/ 20 июня 2019

Возвращает экземпляр класса Child, а не родительского класса.

@Module
public class InteractorModule {
    @Provides
    public InteractorSuma provideSuma() {
        return new InteractorSuma();
    }

    @Provides
    public InteractorResta provideResta() {
        return new InteractorResta();
    }

    @Provides
    public InteractorDivision provideDiv() {
        return new InteractorDivision();
    }

    @Provides
    public InteractorMultiplicacion provideMult() {
        return new InteractorMultiplicacion();
    }
} 
...