Usando o Dagger para injeção de dependência em construtores

Então, atualmente estou redesenhando um aplicativo Android meu para usarPunhal. Meu aplicativo é grande e complicado, e recentemente me deparei com o seguinte cenário:

O objeto A requer uma instância especial do DebugLogger, que é um candidato perfeito para injeção. Em vez de passar em torno do logger, posso apenas injetá-lo através do construtor de A. Isso é algo como isto:

class A
{
    private DebugLogger logger;

    @Inject
    public A(DebugLogger logger)
    {
        this.logger = logger;
    }

    // Additional methods of A follow, etc.
}

Até agora isso faz sentido. No entanto, A precisa ser construído por outra classe B. Múltiplas instâncias de A devem ser construídas, então seguindo a maneira de Dagger de fazer as coisas, eu simplesmente informo umaProvider<A> em B:

class B
{
    private Provider<A> aFactory;

    @Inject
    public B(Provider<A> aFactory)
    {
        this.aFactory = aFactory;
    }
}

Ok, bom até agora. Mas espere, de repente A precisa de entradas adicionais, como um inteiro chamado "quantidade" que é vital para sua construção. Agora, meu construtor para A precisa ficar assim:

@Inject
public A(DebugLogger logger, int amount)
{
...
}

De repente, esse novo parâmetro interfere na injeção. Além disso, mesmo que isso funcionasse, não haveria maneira de passar "quantidade" ao recuperar uma nova instância do provedor, a menos que eu esteja enganado. Há várias coisas que eu poderia fazer aqui, e minha pergunta é qual é a melhor?

Eu poderia refatorar A adicionando umsetAmount() método que se espera que seja chamado após o construtor. Isso é feio, no entanto, porque me obriga a atrasar a construção de A até que "quantidade" tenha sido preenchida. Se eu tivesse dois parâmetros, "quantidade" e "frequência", então eu teria dois setters, o que significaria verificação complicada para garantir que a construção de A seja retomada depois que ambos os setters forem chamados, ou eu teria que adicionar ainda um terceiro método na mistura, da seguinte forma:

(Somewhere in B):

A inst = aFactory.get();
inst.setAmount(5);
inst.setFrequency(7);
inst.doConstructionThatRequiresAmountAndFrequency();

A outra alternativa é que eu não uso injeção baseada em construtor e uso injeção baseada em campo. Mas agora tenho que tornar meus campos públicos. Isso não é bom para mim, porque agora sou obrigado a revelar dados internos de minhas aulas para outras classes.

Até agora, a única solução relativamente elegante que consigo pensar é usar injeção baseada em campo para provedores, da seguinte forma:

class A
{
    @Inject
    public Provider<DebugLogger> loggerProvider;
    private DebugLogger logger;

    public A(int amount, int frequency)
    {
        logger = loggerProvider.get();
        // Do fancy things with amount and frequency here
        ...
    }
}

Mesmo assim, não tenho certeza sobre o momento, já que não tenho certeza se Dagger vai injetar o provedor antes que meu construtor seja chamado.

Existe uma maneira melhor? Estou apenas sentindo falta de algo sobre como Dagger funciona?

questionAnswers(4)

yourAnswerToTheQuestion