2014-07-10 15 views
5

Próbuję użyć Dagger do wykonania iniekcji Dependency w aplikacji, którą buduję, i napotkam problem z konstruowaniem odpowiednich DAG-ów, gdy mam moduł jednego pakietu w zależności od wartości dostarczonych przez wtryskiwacz (prawdopodobnie dostarczone przez inny moduł).Moduł w zależności od innego modułu w Sztyletie

Jeśli mam prosty moduł dla niektórych zmiennych konfigurowalne (które mogłyby chcę zamienić się w środowiskach testowych, na przykład)

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

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

i inny moduł zależy od niego, na przykład

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

Linia gdzie staram się bootstrap zastrzyk w konstruktor nie powiedzie się, a ona twierdzi, że nie określono wyraźne injects linię w odpowiednim module.

metodą prób i błędów widzę ten znika, gdy w @Module dodać linię include = ConfigModule.class, ale wydaje mi się semantycznie niewłaściwy, ponieważ a) DAG będę tworzyć będzie teraz zawierać wartości obu modułów , a nie tylko jeden, oraz b) pokonuje cel/elastyczność DI przede wszystkim w celu połączenia konkretnego Modułu, zamiast po prostu pozwolić Daggerowi wprowadzić odpowiednią wartość.

Przypuszczam, że nie powinienem tworzyć wykresu obiektowego z this tylko po to, aby go wstrzyknąć? Ale potem napotkasz emisję nie powiązanie określonego modułu ...

zwięźle:

  • Co to jest „właściwy” sposób, aby wstrzyknąć wartości do jednego modułów, które mogą być dostarczane z innymi modułami? Tutaj używam wtrysku polowego, ale moje eksperymenty z wtryskiem konstruktora również zaowocowały wieloma niepowodzeniami.
  • Zależnie od tego, kiedy należy użyć addsTo vs. includes?

Dzięki :)

Odpowiedz

22

Nie trzeba robić żadnej z wtryskiem (pola lub konstruktora) w jednym module z innego wyraźnie. Po prostu użyj addsTo i includes. includes pozwala dodawać moduły do ​​innych i używać wszystkiego, co zapewniają. Przykład:

@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 jest używany ObjectGraph.plus(Object... modules). Gdy wykres jest już utworzony i zawiera kilka modułów (np. W klasie Aplikacja), możesz utworzyć nowy wykres (np. W Aktywności), używając plus. Przykład:

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

Ponadto można sprawdzić this przykład do tworzenia zakresów wykresach.

+0

Hej, dziękuję bardzo za to. Przepraszam za późne zatwierdzenie, musiałem zgasić kilka innych pożarów. Nie jestem pewien, czy jestem w 100% zrozumiały co do wszystkiego, ale użycie "Injectable" zapewnia metody (o których nie wiedziałem, że potrafisz!). –

Powiązane problemy