Dagger no puede encontrar miembros inyectables en un módulo
Estoy usando Dagger para la inyección de la dependencia en un proyecto de Androide, y puedo compilar y construir la multa de la aplicación. El gráfico de objeto parece estar correcto y funcionando, pero cuando agrego dagger-compilador como una dependencia para obtener errores en tiempo de compilación, reporta algunos errores extraños:
[ERROR] error: No binding for com.squareup.tape.TaskQueue<com.atami \ .mgodroid.io.NodeIndexTask> required by com.atami \ .mgodroid.ui.NodeIndexListFragment for com.atami.mgodroid \ .modules.OttoModule [ERROR] error: No binding for com.squareup.tape.TaskQueue<com.atami \ .mgodroid.io.NodeTask> required by com.atami \ .mgodroid.ui.NodeFragment for com.atami.mgodroid.modules.OttoModule [ERROR] error: No injectable members on com.squareup.otto.Bus. Do you want to add an injectable constructor? required by com.atami. \ mgodroid.io.NodeIndexTaskService for com.atami.mgodroid.modules.TaskQueueModule
El error de Otto se parece al que Eric Burke menciona en su presentación sobre la Anatomía de Android App acerca de no tener una anotación @Provides
, pero como se puede ver a continuación lo hago.
- Square Dagger IllegalStateException: No se pudo cargar el adaptador de módulo para la clase MyApplicationModule
- Dagger para Android: Inyección de una actividad en el gráfico de objetos después de llamar a setContentView
- Inyectar dependencias en singleton con Dagger?
- Android Dagger Dependency Injection falla en campos privados
- Dagger 2 - Inyectar bibliotecas de terceros en servicios y actividades de Android
Mis módulos Otto y TaskQueue son los siguientes:
@Module( entryPoints = { MGoBlogActivity.class, NodeIndexListFragment.class, NodeFragment.class, NodeActivity.class, NodeCommentFragment.class, NodeIndexTaskService.class, NodeTaskService.class } ) public class OttoModule { @Provides @Singleton Bus provideBus() { return new AsyncBus(); } /** * Otto EventBus that posts all events on the Android main thread */ private class AsyncBus extends Bus { private final Handler mainThread = new Handler(Looper.getMainLooper()); @Override public void post(final Object event) { mainThread.post(new Runnable() { @Override public void run() { AsyncBus.super.post(event); } }); } } }
…
@Module( entryPoints = { NodeIndexListFragment.class, NodeFragment.class, NodeIndexTaskService.class, NodeTaskService.class } ) public class TaskQueueModule { private final Context appContext; public TaskQueueModule(Context appContext) { this.appContext = appContext; } public static class IOTaskInjector<T extends Task> implements TaskInjector<T> { Context context; /** * Injects Dagger dependencies into Tasks added to TaskQueues * * @param context the application Context */ public IOTaskInjector(Context context) { this.context = context; } @Override public void injectMembers(T task) { ((MGoBlogApplication) context.getApplicationContext()) .objectGraph().inject(task); } } public static class ServiceStarter<T extends Task> implements ObjectQueue.Listener<T> { Context context; Class<? extends Service> service; /** * Starts the provided service when a Task is added to the queue * * @param context the application Context * @param service the Service to start */ public ServiceStarter(Context context, Class<? extends Service> service) { this.context = context; this.service = service; } @Override public void onAdd(ObjectQueue<T> queue, T entry) { context.startService(new Intent(context, service)); } @Override public void onRemove(ObjectQueue<T> queue) { } } @Provides @Singleton TaskQueue<NodeIndexTask> provideNodeIndexTaskQueue() { ObjectQueue<NodeIndexTask> delegate = new InMemoryObjectQueue<NodeIndexTask>(); TaskQueue<NodeIndexTask> queue = new TaskQueue<NodeIndexTask>( delegate, new IOTaskInjector<NodeIndexTask>(appContext)); queue.setListener(new ServiceStarter<NodeIndexTask>( appContext, NodeIndexTaskService.class)); return queue; } @Provides @Singleton TaskQueue<NodeTask> provideNodeTaskQueue() { ObjectQueue<NodeTask> delegate = new InMemoryObjectQueue<NodeTask>(); TaskQueue<NodeTask> queue = new TaskQueue<NodeTask>( delegate, new IOTaskInjector<NodeTask>(appContext)); queue.setListener(new ServiceStarter<NodeTask>( appContext, NodeTaskService.class)); return queue; } }
…
/** * Module that includes all of the app's modules. Used by Dagger * for compile time validation of injections and modules. */ @Module( includes = { MGoBlogAPIModule.class, OttoModule.class, TaskQueueModule.class } ) public class MGoBlogAppModule { }
- ¿Se aplican también a Dagger "Evita los marcos de inyección de dependencia" en la Guía de memoria de Android?
- ¿Hay documentación sobre cuándo Dagger regresa a la reflexión al inyectar dependencias?
- ¿Cómo usar la biblioteca dagger en el proyecto de la biblioteca android?
- ¿Se puede utilizar Spring Framework en aplicaciones android?
- Bean and EBean conception Anotaciones para Android
- Uso de Dagger para inyección de dependencia en constructores
- Dagger con Android: ¿Cómo puedo inyectar el contexto actual?
- Módulo dependiendo de otro módulo en Dagger
El análisis completo del gráfico de Dagger funciona desde un módulo completo. Ie @Module (complete = true), que es el valor predeterminado. Debido a que es el valor predeterminado, dagger, por defecto, asumirá que todos los enlaces están disponibles desde ese módulo o los módulos que incluye de forma explícita.
En este caso, usted ha dado dos módulos que usted dice están completos, pero Dagger no tiene ninguna manera de atar estos juntos en tiempo de compilación sin una señal adicional. En resumen, sin OttoModule saber acerca de TaskQueueModule, el compilador intentará analizar OttoModule por su completitud declarada, y fallar, ya que no ahora sobre TaskQueueModule.
Modifique la anotación de OttoModule como tal:
@Module( includes = TaskQueueModule.class, entryPoints = { MGoBlogActivity.class, NodeFragment.class, NodeActivity.class, NodeCommentFragment.class, NodeIndexTaskService.class, NodeTaskService.class } )
Y entonces Dagger sabrá que para que OttoModule esté completo, incluye el otro módulo como parte de su definición completa.
Nota: dagger-compilador no puede detectar que TaskQueueModule está allí en la vía de acceso de clase y sólo "saber" que el desarrollador pensaba que se utilizará con OttoModule sin esa señal adicional. Por ejemplo, es posible que tenga varios módulos que definen las colas de tareas y cuál seleccionaría? La declaración debe ser explícita.
- Aplicación de Android vs. Actividad
- EventBus: la actividad no recibe un evento cuando la aplicación está en segundo plano