support implement google compiler annotationprocessor android dagger dagger-2

android - implement - Dagger 2 error: la dependencia "no se puede proporcionar sin un @Inject constructor" mientras que realmente se anotó con @Inject



implement dagger 2 android (6)

Empecé a usar Dagger 2 y me enfrenté a un extraño problema que me parece un error.

Tengo 3 módulos, que se componen en un subcomponente, que a su vez amplía / más componente de nivel superior.

El subcomponente es bastante simple: solo combinación de módulos y un único punto de inyección:

@Singleton @Subcomponent( modules = { NavigationDrawerModule.class, NavigationListModule.class, SwitcherModule.class } ) public interface NavigationDrawerComponent { NavigationDrawerFragment inject(NavigationDrawerFragment object); }

Los primeros módulos se ven así: proporciona dependencias generales a nivel de fragmento:

@Module public class NavigationDrawerModule { private final Activity activity; private final View rootView; private final LoaderManager loaderManager; public NavigationDrawerModule(Activity activity, View rootView, LoaderManager loaderManager) { this.activity = activity; this.rootView = rootView; this.loaderManager = loaderManager; } @Provides @Singleton EventBus provideLocalBus() { return EventBus.builder().build(); } @Provides @Singleton View provideViewRoot() { return rootView; } @Provides @Singleton LoaderManager provideLoaderManager() { return loaderManager; } @Provides @Singleton Context provideContext() { return activity; } }

El segundo módulo se ve así: proporciona presentador / controlador y sus dependencias para un subconjunto de UI en pantalla:

@Module public class SwitcherModule { @Provides SwitchController provideSwitcherController(SwitchControllerImpl impl) { return impl; } @Provides SwitcherView provideSwitcherView(SwitcherViewImpl impl) { return impl; } }

Tercer módulo: otro presentador / controlador para un subconjunto de UI:

@Module public class NavigationListModule { @Provides @Singleton NavigationListController provideNavigationListController(NavigationListControllerImpl impl) { return impl; } @Provides @Singleton NavigationListView provideNavigationListView(NavigationListViewImpl impl) { return impl; } }

Parte relevante del fragmento que se está inyectando:

@Inject SwitchController identitySwitchController; @Inject SwitcherView identitySwitcherView; @Inject NavigationListController navigationListController; @Inject NavigationListView navigationListView;

NavigationListControllerImpl implementa el siguiente constructor:

@Inject public NavigationListControllerImpl(Context ctx, EventBus bus) { this.ctx = ctx; this.bus = bus; }

El error que obtengo del compilador Dagger 2 es el siguiente:

error: ...sidenavigation.navigationlist.NavigationListControllerImpl cannot be provided without an @Inject constructor or from an @Provides-annotated method. ...sidenavigation.NavigationDrawerFragment.navigationListController [injected field of type: ...sidenavigation.navigationlist.NavigationListController navigationListController] ...sidenavigation.navigationlist.NavigationListModule.provideNavigationListController(...sidenavigation.navigationlist.NavigationListControllerImpl impl) [parameter: ...sidenavigation.navigationlist.NavigationListControllerImpl impl]

El error se queja de la falta del constructor @Inject-annotated, ¡pero existe! Si reemplazo la creación de instancia de NavigationListControllerImpl implícita (pasando por @Provides parameter) con explicit (with new ), dagger comienza a quejarse del mismo error pero ahora para el objeto presentador que es la segunda entrada en el mismo módulo, y así sucesivamente.

Toda esta situación parece muy extraña, y me gustaría escuchar algunas aportaciones de los usuarios más experimentados de Dagger 2 (¿y los desarrolladores?).

¡Gracias de antemano!


El GlobalComponent y el subcomponente NavigationDrawerComponent deben tener diferentes ámbitos. Use @Singleton para su GlobalComponent y algún otro alcance para el subcomponente.

De lo contrario, si aplica el mismo alcance al GlobalComponent y al subcomponente, también debe declarar los módulos de su subcomponente en su componente global:

@Component( // modules from subcomponent must be declared here also modules = {NavigationListModule.class, SwitcherModule.class, NavigationDrawerModule.class, ...} ) @Singleton public interface GlobalComponent { NavigationDrawerComponent plus(NavigationDrawerModule module); }

Para su caso de uso, también puede usar dependencias de componentes. Por ejemplo:

@Component( dependencies = GlobalComponent.class, modules = {NavigationListModule.class, SwitcherModule.class, NavigationDrawerModule.class} ) @YourOtherDaggerScope // @Singleton scope won''t work here, it must be a different scope public interface NavigationDrawerComponent extends GlobalComponent { // extend the parent component if you wish to get access to parent dependencies NavigationDrawerFragment inject(NavigationDrawerFragment object); }


Llegó a este tema hoy también. Para mí, hubo un problema con el proceso de anotación (en Android Studio 2.2 con gradle 2.x).

En lugar de ~~ apt ~~ Utilicé el programa de anotación que utilicé

annotationProcessor ''com.google.dagger:dagger-compiler:2.6''

y ahora está funcionando.


Obtuve el mismo error porque olvidé exponer los objetos proporcionados por los módulos en el componente principal a los otros componentes que dependen de él.

Ejemplo del componente principal:

@Singleton @Component(modules = {AppModule.class}) public interface AppComponent { AppPref exposeAppPref(); /* my issue was caused by forgot this line, the method name doesn''t matter, what matters is the object type AppPref provided in the AppModule that you want it to be available in the component that declares this component as one of its dependencies*/ }

Componente de muestra que hace que el componente anterior sea una dependencia

@UserScope @Component (dependencies = {AppComponent.class}) public interface ActivityComponent { void inject(MainActivity activity); }

Actualizar:

AppModule:

... @Provides @Singleton AppPref provideAppPref() { return appPref; } ...


Parece que es el mismo tipo de informes de daga de error para muchos errores. En mi caso, mi objetivo de inyección esperaba una clase concreta (Presentador) mientras que el módulo que proporciona el presentador solo devolvía la interfaz (DemoContract.Presenter)

Tan cambiado de

@Inject public Presenter mDemoPresenter;

a

@Inject public DemoContract.Presenter mDemoPresenter;

y el módulo que proporciona el presentador se ve así:

@Module public class DiDemoPresenterModule { private final DemoContract.View mView; DiDemoPresenterModule(MainActivity mView) { this.mView = mView; } @Provides public DemoContract.Presenter providesDemoPresenter(Repository repository) { return new DemoPresenter(repository, mView); } }


Parece que ya descubrí lo que estaba mal en la configuración de mi Dagger 2. No es posible usar el mismo alcance en componentes y subcomponentes. Se requiere definir un nuevo alcance para el subcomponente. En mi caso, terminé creando el sub-componente @Screen scope for me.

Diría que este es un pequeño pero muy molesto defecto en Dagger 2. Aparentemente dagger-compiler informa un error agradable y comprensible sobre los mismos ámbitos en un componente padre y componente hijo si el componente hijo se extiende con un componente padre como dependencia. Pero el compilador informa el error completamente engañoso si el componente principal y el subcomponente secundario comparten el mismo alcance.

Gracias, @lukas, por darme una pista aquí https://.com/a/30383088/808313 que condujo a una resolución del problema.


Se encontró con el mismo problema al intentar crear Subcomponentes, pero parece estar arreglado en Dagger 2.0.1.