2015-04-23 13 views
7

Ho una semplice configurazione di prova di Dagger 2, basata su http://konmik.github.io/snorkeling-with-dagger-2.html. Inietta un PreferenceLogger che emette tutte le preferenze. Nella classe iniettata, posso @Inserire più classi.Dagger 2 e implementazioni di interfaccia

public class MainActivity extends Activity { 
    @Inject PreferencesLogger logger; 
    @Inject MainPresenter presenter; 

    @Override protected void onCreate(Bundle savedInstanceState) { 
    MyApplication.getComponent().inject(this); 
    presenter.doStuff(); 
     logger.log(this); 
    } 
} 


public class PreferencesLogger { 

    @Inject OkHttpClient client; 
    @Inject public PreferencesLogger() {} 

    public void log(Contect context) { 
    // this.client is available 
    } 
} 

Quando eseguo questo, logger è impostato, e dentro il PreferencesLogger.log OkHttpClient è impostato correttamente. Quindi questo esempio funziona come previsto. Ora sto cercando di ottenere una struttura MVP sul posto. C'è un'interfaccia MainPresenter con un'implementazione. Nella MainActivity a impostare una:

@Inject MainPresenter presenter; 

così ho potuto passare questo MainPresenter con un'alternativa (debug o test) attuazione. Ovviamente, ora ho bisogno di un modulo per specificare quale implementazione voglio utilizzare.

public interface MainPresenter { 
    void doStuff(); 
} 

public class MainPresenterImpl implements MainPresenter { 

    @Inject OkHttpClient client; 

    public MainPresenterImpl() {} 

    @Override public void doStuff() { 
    // this.client is not available  
    } 
} 


@Module public class MainActivityModule { 
    @Provides MainPresenter provideMainPresenter() { 
     return new MainPresenterImpl(); 
    } 
} 

Un problema ora si verifica che OkHttpClient non viene più iniettato. Ovviamente potrei alterare il modulo per accettare un parametro OkHttpClient, ma non penso che questo sia il modo consigliato di farlo. C'è una ragione per cui MainPresenterImpl non viene iniettato correttamente?

+0

ho fatto una domanda relativa qui: http://stackoverflow.com/questions/30555285/dagger2-injecting-implementation-classes-with-component – EpicPandaForce

+0

un'occhiata a questo progetto articolo e campione che potrebbe aiutare: https://medium.com/@m_mirhoseini/yet-another-mvp-article-part-1-lets-get-to-know-the-project-d3fd553b3e21#.6y9ze7e55 –

risposta

4

Diversamente dall'iniezione del costruttore, i campi annotati delle dipendenze @Inject costruiti nei metodi @Provides non possono essere automaticamente iniettati. Essere in grado di iniettare i campi richiede un componente che fornisce il tipo di campo nei suoi moduli, e nei metodi del fornitore stessi, una tale implementazione non è disponibile.

Quando il campo presenter viene iniettato in MainActivity, tutto ciò che accade è il metodo del provider è chiamato e presenter è impostato sul suo valore di ritorno. Nell'esempio, il costruttore no-args non esegue l'inizializzazione e nemmeno il metodo provider, quindi non viene eseguita alcuna inizializzazione.

Il metodo provider tuttavia ha accesso alle istanze di altri tipi fornite nel modulo tramite i relativi parametri. Penso che l'utilizzo di parametri nel metodo provider sia in realtà l'approccio suggerito (anche l'unico) per "iniettare" le dipendenze del tipo fornito, perché le indica esplicitamente come dipendenze all'interno del modulo, il che consente a Dagger di generare un errore durante la compilazione -time se non possono essere soddisfatti.

Il motivo per cui attualmente non genera un errore è perché MainPresenterImplpotrebbe ottenere la sua dipendenza OkHttpClient soddisfatta se MainPresenterImpl e non MainPresenter era da qualche parte un obiettivo per l'iniezione. Dagger non può creare un metodo di iniezione dei membri per il tipo di interfaccia, perché come interfaccia non può avere campi iniettabili e non inietterà automaticamente i campi del tipo di implementazione, perché fornisce solo il metodo del provider ritorna.

4

Potresti essere in grado di iniettare il tuo MainPresenterImpl utilizzando l'iniezione del costruttore.

/* unscoped */ 
public class MainPresenterImpl implements MainPresenter { 

    @Inject 
    OkHttpClient client; 

    @Inject 
    public MainPresenterImpl() { 
    } 

    @Override public void doStuff() { 
     // this.client is now available! :) 
    } 
} 


@Module 
public class AppModule { 
    private MyApplication application; 

    public AppModule(MyApplication application) { 
     this.application = application; 
    } 

    @Provides 
    /* unscoped */ 
    public MyApplication application() { 
     return application; 
    } 
} 

@Module 
public abstract class MainActivityModule { 
    @Binds public abstract MainPresenter mainPresenter(MainPresenterImpl mainPresenterImpl); 
} 
Problemi correlati