Ошибка кинжала 2: зависимость «не может быть предоставлена ​​без конструктора @Inject», в то время как она фактически аннотируется с помощью @Inject

Я начал использовать Dagger 2 и столкнулся с странной проблемой, которая выглядит как ошибка для меня.

У меня есть 3 модуля, которые состоят из одного подкомпонента, который, в свою очередь, расширяет / плюсы компонента более высокого уровня.

Подкомпонент довольно прост: просто комбинация модулей и единственная точка инъекции:

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

Первые модули выглядят следующим образом: он обеспечивает общие зависимости уровня фрагмента:

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

Второй модуль выглядит следующим образом: он предоставляет презентатор / контроллер и их зависимости для подмножества пользовательского интерфейса на экране:

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

Третий модуль – другой ведущий / контроллер для подмножества пользовательского интерфейса:

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

Соответствующая часть фрагмента, который вводится:

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

NavigationListControllerImpl реализует следующий конструктор:

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

Ошибка, которую я получаю от компилятора Dagger 2, такова:

 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] 

Ошибка жалуется на отсутствие конструктора @ Inject-annotated, но он существует! Если я заменил неявное создание экземпляра NavigationListControllerImpl (передавая через параметр @Provides ) с явным (с new ), кинжал начинает жаловаться на ту же ошибку, но теперь для объекта-презентатора, который является второй записью в том же модуле и т. Д.

Вся эта ситуация выглядит очень странно, и я хотел бы услышать некоторые материалы от более опытных пользователей Dagger 2 (и разработчиков?).

Заранее спасибо!

Solutions Collecting From Web of "Ошибка кинжала 2: зависимость «не может быть предоставлена ​​без конструктора @Inject», в то время как она фактически аннотируется с помощью @Inject"

У меня такая же ошибка, потому что я забыл разоблачить объекты, предоставленные модулями в родительском компоненте, другим компонентам, зависящим от него.

Пример родительского компонента:

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

Пример компонента, который делает вышеуказанный компонент зависимым

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

Похоже, я выяснил, что случилось с настройкой Dagger 2. Нельзя использовать ту же область действия как в компоненте, так и подкомпонентах. Требуется определить новую область для подкомпонента. В моем случае я закончил создание области @Screen для подкомпонента.

Я бы сказал, что это маленький, но очень раздражающий дефект в кинжале 2. Видимо, компилятор кинжалов сообщает о приятной и понятной ошибке о тех же областях в родительском компоненте и дочернем компоненте, если дочерний компонент расширен с родительским компонентом как зависимость. Но полностью вводящая в заблуждение ошибка сообщается компилятором, если родительский компонент и дочерний подкомпонент используют одну и ту же область.

Спасибо, @lukas, за то, что вы указали мне https://stackoverflow.com/a/30383088/808313, что привело к решению проблемы.

GlobalComponent и субкомпонент NavigationDrawerComponent должны иметь разные области применения. Используйте @Singleton для своего GlobalComponent и еще одну область для подкомпонента.

В противном случае, если вы примените ту же область действия к GlobalComponent и к подкомпоненту, вы также должны объявить модули своего подкомпонента в своем глобальном компоненте:

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

Для вашего случая использования вы также можете использовать зависимости компонентов. Например:

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

Сегодняшний этот вопрос. Для меня возникла проблема с обработкой аннотаций (на Android Studio 2.2 с градиентом 2.x).

Вместо ~~ apt ~~ я использовал обработчик annotationProcessor, который я использовал

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

И теперь он работает.

При попытке создания подкомпонентов произошла одна и та же проблема, но, похоже, она исправлена ​​в Dagger 2.0.1.

Кажется, это то же самое, что и копытные сообщения об ошибках для многих ошибок. В моем случае моя целевая инъекция ожидала конкретного класса (Presenter), где, поскольку модуль, который предоставляет презентатору, возвращал только интерфейс (DemoContract.Presenter)

Так что изменилось

 @Inject public Presenter mDemoPresenter; 

в

 @Inject public DemoContract.Presenter mDemoPresenter; 

И модуль, который предоставляет презентатор, выглядит следующим образом:

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