How to Fix Dagger 2 Error '... Cannot Be Provided [...]'

dagger2 is throwing an error: cannot be provided without an @Provides-annotated method. in my android project's build

As suggested in this answer, just add your App class in the android manifest under the application tag.

<application ... 
android:name = ".App" ...>
...

How do I fix Dagger 2 error '... cannot be provided [...]'?

tl;dr You forgot to either add an @Inject to your constructor so that Dagger can use Constructor Injection to provide the object, or you need some method in one of your Modules that creates or binds the object.


What's going on?

Have a good look at the error message: It states that you try to request a dependency but Dagger has no way to provide or create it. It simply does not know how to, because it cannot be provided without an @Inject constructor or from an @Provides-annotated method.

A close look at the error message shows the class (a) that you are trying to provide and the component (b) that needs it.

com.example.MyDependency (a) is provided at

com.example.MyComponent.myDependency() (b)

You have to make sure that (b) can create or provide (a) to fix your issue.

It looks a bit more complex if you tried to inject your dependency somewhere else, but you can still see the full stack of events—in this case a constructor injection missing a dependency. The class (a) that you are trying to provide and the location (b) where Dagger tried injecting it. It also tells you where that dependent class was created (c) and again the component (d) that failed providing (a).

com.example.MyDependency cannot be provided without an @Inject constructor or from an @Provides-annotated method.

com.example.MyDependency (a) is injected at

com.example.DependentClass.(dependency) (b)

com.example.DependentClass is provided at (c)

com.example.MyComponent.myDependency() (d)

The same applies here: Make sure that (d) knows how to provide (a) and you're good to go.

How do I fix this?

Have a look at the error as shown above. Make sure you understand where it occured and what you are trying to inject. Then tell Dagger how to provide your object.

an @Inject constructor

As the error states, you try to use MyDependency but MyComponent does not know how to do that. If we have a look at the example it becomes clear why:

class MyDependency {}

The class has no @Inject annotated constructor! And there is no other module in the component, so there is nothing Dagger could do.

If you want to use constructor injection you can just add an @Inject annotated constructor and are done. Dagger will see this constructor and know how to create your class.

class MyDependency {
@Inject
MyDependency() { /**/ }
}

That is all you have to do when you can make use of constructor injection.

from an @Provides-annotated method

The error message states a second option, which allows you to provide an object if you don't want—or can't—use constructor injection. You can also add a @Provides annotated method to a module and add this module to your component.

@Module
class MyModule {
@Provides
MyDependency provideMyDependency() {
return new MyDependency();
}
}

@Component(modules = MyModule.class)
interface MyComponent {
MyDependency myDependency();
}

This way Dagger can use your module to create and provide your dependency. It is a little bit more boilerplate than using Constructor Injection, but you will have to use Modules for everything that needs further setup or that does not have an annotated constructor, e.g. third party libraries like Retrofit, OkHttp, or Gson.


There are also other ways to provide a dependency from a component. A @SubComponent has access to its parents dependencies, and a component dependency can expose some of its dependencies to its dependent components. But at some point everything Dagger provides needs to either have an @Inject constructor or a Module providing it.

But I did add MyDependency!

Pay close attention to the details. You probably are using an interface when you are only providing the implementation, or try to use a parent class when Dagger only knows about the subclass.

Maybe you added a custom @Qualifier or used @Named("typeA") with it. To Dagger this is a completely different object! Double check that you actually provide and request the same dependency.

Read the error and make sure that you either have an @Inject annotated constructor, a module that has a @Provides method that provides that type, or a parent component that does.

What if I want to provide an implementation for my interface?

A simple example like the following shows how one class extends another:

class MyDependency extends MyBaseDependency {
@Inject MyDependency() { super(); }
}

This will inform Dagger about MyDependency, but not about MyBaseDependency.

If you have one class implementing an interface or extending a super class you have to declare that. If you provide MyDependency this does not mean that Dagger can provide MyBaseDependency. You can use @Binds to tell Dagger about your implementation and provide it when the super class is required.

@Module
interface MyModule {
@Binds
MyBaseDependency provideMyBaseDependency(MyDependency implementation);
}

Dagger 2 error: dependency “cannot be provided without an @Provides-annotated method

Seems like I've figured out what was wrong

the problem. the DeliveriesModule which is a module of DeliveriesActivity so i have to make another Module for DeliveriesListFragment and provide the DeliveryListUseCase

Thank you, @Blackbelt, for giving me a hint

Dagger 2 error: dependency cannot be provided without an @Inject constructor while it actually annotated with @Inject

Seems like I've figured out what was wrong with my Dagger 2 setup. It's not possible to use the same scope in both component and subcomponents. It's required to define a new scope for subcomponent. In my case I've ended up creating @Screen scope for me subcomponent.

I'd say that this is a small but very annoying defect in Dagger 2. Apparently dagger-compiler reports nice and understandable error about the same scopes in a parent component and child component if child component is extended with a parent component as dependency. But completely misleading error is reported by the compiler if parent component and child subcomponent share the same scope.

Thank you, @lukas, for giving me a hint here https://stackoverflow.com/a/30383088/808313 that led to a problem resolution.

Dagger2 Can't provide dependency of activity to dagger

dagger.android does do this automatically: See the explicit version of the binding that @ContributesAndroidInjector generates for you, where the generated AndroidInjector.Factory contains a @BindsInstance binding of the type you request here.

This isn't working for you because you are injecting MainActivity in a binding that is installed on your top-level component. This is a problem because AppComponent will exist before the Activity does, and will also be replaced as Android recreates the Activity: Passing an instance through @Component.Builder is not a way around this problem.

Instead, move your FactoryVmModule::class to within the subcomponent that @ContributesAndroidInjector generates, which you can do by including it in the modules attribute on @ContributesAndroidInjector. Dagger will create a different subcomponent instance per Activity instance, so your FactoryVmModule will always have a fresh binding to MainActivity.

@Module
abstract class MainActivityModule {
@ContributesAndroidInjector(
modules = [ViewModelModule::class, FactoryVmModule::class]
)
abstract fun injectMainActivity(): MainActivity
}

I moved your ViewModelModule class there as well; though it's possible you could leave it in your top-level Component if it doesn't depend on anything belonging to the Activity, you might want to keep them together. Bindings in subcomponents inherit from the application, so you can inject AppComponent-level bindings from within your Activity's subcomponent, but not the other way around. This means you won't be able to inject VM instances (here, TestVM) outside your Activity, but if they depend on the Activity, you wouldn't want to anyway: Those instances might go stale and keep the garbage collector from reclaiming your finished Activity instances.



Related Topics



Leave a reply



Submit