android - medium - Daga e inyecciones anidadas
dagger android support (4)
Estoy usando Dagger para inyectar dependencias en una aplicación de Android, y tropecé con un problema que no estoy del todo seguro de cómo resolverlo de una manera limpia.
Lo que intento lograr es instanciar ayudantes e inyectarlos dentro de mi actividad, y hacer que estos ayudantes también contengan miembros inyectados.
Que funciona
La actividad donde mi ayudante está siendo inyectado:
public class MyActivity extends Activity {
@Inject SampleHelper helper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MyApplication) getApplication()).inject(this);
Log.i("debug", "helper = " + helper);
Log.i("debug", "helper context = " + helper.context);
}
}
La aplicación que crea el gráfico de objetos:
public class MyApplication extends Application {
private ObjectGraph graph;
@Override
public void onCreate() {
super.onCreate();
graph = ObjectGraph.create(getModules());
}
private Object[] getModules() {
return new Object[] { new MyModule(this) };
}
public void inject(Object target) {
graph.inject(target);
}
}
La inyección funciona perfectamente cuando instalo directamente una clase SampleHelper, que a su vez recibe un contexto de aplicación inyectada:
@Singleton
public class SampleHelper {
@Inject public Context context;
@Inject
public SampleHelper() {}
}
Con el siguiente módulo:
@Module(
injects = { MyActivity.class },
complete = false,
library = true
)
public class MyModule {
private final MyApplication application;
public MyModule(MyApplication application) {
this.application = application;
}
@Provides @Singleton Context provideApplicationContext() {
return application;
}
}
Lo que no funciona
Sin embargo, cuando se separa la interfaz auxiliar de su implementación:
public interface SampleHelper {
}
@Singleton
public class SampleHelperImpl implements SampleHelper {
@Inject public Context context;
@Inject
public SampleHelperImpl() {}
}
Y agrega esto al módulo de daga:
public class MyModule {
...
// added this method
@Provides @Singleton public SampleHelper provideSampleHelper() {
return new SampleHelperImpl();
}
...
}
El contexto no se inyecta en mi SampleHelperImpl, como hubiera esperado. Ahora, supongo que esto se debe a que SampleHelperImpl se instancia a través de una llamada de constructor directa en lugar de una llamada de constructor iniciada por inyección, porque MyModule # provideApplicationContext () ni siquiera se llama, así que supongo que me falta algo sobre Dagger (que es Probablemente, ya que mis experiencias DI anteriores solo incluían a Spring).
¿Alguna idea sobre cómo inyectar mi contexto en la implementación de mi ayudante inyectado, de una manera "limpia Daga"?
¡Muchas gracias!
En caso de que alguien esté interesado, al implementar un método @Provides en un módulo de daga, puede obtener instancias de objetos manejados con daga de esa manera:
@Provides @Singleton public SampleHelper provideSampleHelper(Context context) {
SampleHelper helper = new SampleHelperImpl();
helper.setContext(context);
return helper;
}
Esto funciona, pero todavía siento que es un poco torpe, ya que tengo que llamar explícitamente a mis colaboradores setters (típicamente lo que quieres eliminar con la inyección).
(Esperaré un poco en caso de que alguien venga con una mejor solución)
En términos de inyectar el contexto correcto, es posible que desee echarle un vistazo a esta muestra https://github.com/square/dagger/tree/master/examples/android-activity-graphs .
(Se aplica a Dagger v1.0.1)
Asegúrese de estar usando la inyección de adaptador. Con la inyección reflectante, daga aparentemente no hace una inyección transitiva en objetos @Provides
. Creo que esto es un error.
Esta es una pregunta bastante antigua, pero creo que lo que quieres es esto:
@Provides @Singleton public SampleHelper provideSampleHelper(SampleHelperImpl impl) {
return impl;
}
De esta forma, Dagger creará su SampleHelperImpl
y, por lo tanto, lo inyectará.