¿Cómo le digo a Dagger 2 qué implementación instanciar basada en X?
Dentro de un módulo, si necesito proporcionar una implementación diferente de una interfaz basada en una variable conocida en el momento de la construcción del módulo, puedo poner la lógica dentro del método @Provides para ese tipo de interfaz. Al igual que:
@Module
public class FooModule {
private final State state;
public FooModule(State state) {
this.state = state;
}
@Provides
FooInterface provideFooImplementation() {
switch(state) {
case STATE_1:
return new FooImpl1();
case STATE_2:
return new FooImpl2();
...
case STATE_10:
return new FooImpl10();
}
}
}
Sin embargo, estas implementaciones podrían ser creadas por Dagger. Preferiría decir "Hey, basado en X, quiero que crees una instancia de esta clase para mí"
He considerado un par de opciones.
Cambie el método de suministro para tener en cuenta todas las implementaciones posibles:
@Provides
FooInterface provideFooImplementation(FooImpl1 impl1, FooImpl2 imp2, ..., FooImpl10 impl10) {
switch(state) {
case STATE_1:
return impl1;
case STATE_2:
return impl2;
...
case STATE_10:
return impl10;
}
}
Esto le permite a Dagger crear instancias y satisfacer todas sus dependencias, pero no es una buena idea si cada una de las implementaciones es relativamente grande o costosa de crear.
Cambie el método de suministro para incluir una colección de todas las dependencias para las diferentes implementaciones.
@Provides
FooInterface provideFooImplementation(Context context, Repo repo, HttpClient httpClient, ...) {
switch(state) {
case STATE_1:
return new FooImpl1(context);
case STATE_2:
return new FooImpl2(repo, httpClient);
...
case STATE_10:
return new FooImpl10(context, repo);
}
}
Esto es un poco mejor que la opción 1, ya que Dagger no tiene que crear instancias de cada implementación, sin embargo, aún necesita crear instancias de todas las dependencias, aunque no se puedan usar en todos los casos. También he vuelto a crear los objetos yo mismo, aunque Dagger podría crearlos.
Cree un módulo por implementación e instancia el módulo apropiado. Entonces algo como:
@Module
public FooImpl1Module {
@Provides
FooInterface provideFooImplementation(Context context) {
return new FooImpl1(context);
}
}
Esto estaría bien, pero ahora tengo problemas para definir el componente que depende del módulo.
¿Cuál es la mejor manera de abordar este problema?
Una sugerencia ha sido probar la opción 1 con los parámetros envueltos en Lazy. Entonces solo termino llamando a .get () en uno. Probaré esto cuando pueda y publicaré los resultados