2014-07-10 10 views
5

Sto provando a utilizzare Dagger per fare Dependency Injection su un'app che sto costruendo, e sto incontrando problemi nella costruzione di DAG appropriati quando ho un modulo di un pacchetto in base ai valori forniti dall'iniettore (presumibilmente fornito da un altro modulo).Modulo dipendente da un altro modulo in Dagger

Se ho un modulo semplice per alcune variabili configurabili (che potrei voler scambiare per ambienti di test, per esempio)

@Module(
    injects = DependentModule.class, 
) 
public class ConfigModule { 

    @Provides @Named("ConfigOption") String provideConfigOption() { 
     return "This Module's configurable option!"; 
    } 
} 

e un altro modulo dipende da esso, per esempio

@Module(
    injects = { 
      TopLevelClass.class 
    } 
) 
public class DependentModule { 

    @Inject @Named("ConfigOption") String configOption; 

    public DependentModule() { 
     ObjectGraph.create(this).inject(this); 
     doSomethingWithConfig(configOption); 
    } 

    @Provides @Singleton UsefulValue provideUsefulValue() { 
     // Whatever this module needs to do... 
    } 
} 

La linea dove cerco di bootstrap l'iniezione nel costruttore non riesce e si lamenta che non ho specificato un esplicito injects linea in un modulo corretto.

Attraverso tentativi ed errori che vedo questo va via se in @Module aggiungo una linea include = ConfigModule.class, ma questo mi sembra semanticamente sbagliato, dal momento che a) il DAG sarò creando ora includere i valori di entrambi i moduli , piuttosto che uno solo, eb) sconfigge lo scopo/flessibilità di DI in primo luogo per collegare un modulo specifico piuttosto che semplicemente lasciare che Dagger inietti il ​​valore appropriato.

Suppongo che non debba essere creato un Object Graph con this solo da iniettare in esso? Ma poi ho incontrato il problema di non collegare un modulo specifico ...

brevemente:

  • Qual è il modo 'corretto' per iniettare i valori in uno dei moduli che possono essere forniti da altri moduli? Qui sto usando l'iniezione sul campo, ma i miei esperimenti con l'iniezione del costruttore hanno portato anche a molti fallimenti.
  • In correlazione, quando è opportuno utilizzare addsTo rispetto a includes?

Grazie :)

risposta

22

Non c'è bisogno di fare qualsiasi iniezione (campo o costruttore) in un modulo da un altro in modo esplicito. Basta usare addsTo e includes. includes consente di aggiungere moduli a un altro e utilizzare tutto ciò che forniscono. Esempio:

@Module() 
public class ModuleA { 
    @Provides @Named("ValueA") String provideValueA() { 
     return "This is ValueA"; 
    } 
} 

@Module(
    includes = ModuleA.class 
) 
public class ModuleB { 
    // ValueA comes from ModuleA 
    @Provides @Named("ValueB") String provideValueB(@Named("ValueA") String valueA) { 
     return valueA + " and ValueB"; 
    } 
} 

addsTo viene utilizzato con ObjectGraph.plus(Object... modules). Quando il grafico è già stato creato e contiene alcuni moduli (ad esempio nella classe Applicazione), puoi creare un nuovo grafico (ad esempio in Attività) utilizzando plus. Esempio:

@Module() 
public class ApplicationModule { 
    @Provides @Named("ValueA") String provideValueA() { 
     return "This is ValueA"; 
    } 
} 

@Module(
    addsTo = ApplicationModule.class 
) 
public class ActivityModule { 
    // ValueA comes from ApplicationModule 
    @Provides @Named("ValueB") String provideValueB(@Named("ValueA") String valueA) { 
     return valueA + " and ValueB"; 
    } 
} 

public class DemoApplication extends Application { 
    private ObjectGraph graph; 

    @Override public void onCreate() { 
    super.onCreate(); 
    graph = ObjectGraph.create(getModules().toArray()); 
    } 

    protected List<Object> getModules() { 
     return Arrays.asList(
      new ApplicationModule() 
    ); 
    } 

    public void inject(Object object) { 
     graph.inject(object); 
    } 

    public ObjectGraph getObjectGraph() { 
     return graph; 
    } 
} 

public class DemoActivity extends Activity { 
    private ObjectGraph activityGraph; 

    @Override protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // Create the activity graph by .plus-ing our modules onto the application graph. 
     DemoApplication application = (DemoApplication) getApplication(); 
     activityGraph = application.getApplicationGraph().plus(new ActivityModule()); 

     // Inject ourselves so subclasses will have dependencies fulfilled when this method returns. 
     activityGraph.inject(this); 
    } 

    @Override protected void onDestroy() { 
     // Eagerly clear the reference to the activity graph to allow it to be garbage collected as 
     // soon as possible. 
     activityGraph = null; 
     super.onDestroy(); 
    } 
} 

Inoltre è possibile controllare this esempio per creare ambiti di grafici.

+0

Ehi, grazie mille per questo. Scusa per il ritardo, ho dovuto spegnere altri incendi. Non sono sicuro di essere al 100% chiaro su tutto ciò che ha a che fare con questo, ma usare 'includes' con i metodi Injectable fornisce (che non sapevo che potessi fare!) Era abbastanza. –

Problemi correlati