Reputation: 2647
I'm configuring the new Dagger Android module but I got this error Here's my Component:
@AppScope
@Component(modules = {AppModule.class, NetModule.class})
public interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(ExampleApplication application);
@BindsInstance
Builder appModule(AppModule appModule);
@BindsInstance
Builder netModule(NetModule netModule);
AppComponent build();
}
void inject(ExampleApplication __);
...
Which I build like this in my Application
appComponent = DaggerAppComponent
.builder()
.application(this)
.appModule(new AppModule(this))
.netModule(new NetModule())
.build()
.inject(this);
But I still receive the error
Error:(20, 3) error: @Component.Builder is missing setters for required modules or components: [app.example.com.dagger.AppModule]
According to the documentation that should be right, What am I missing?
For example, this could be a valid Component with a Builder:
@Component(modules = {BackendModule.class, FrontendModule.class})
interface MyComponent {
MyWidget myWidget();
@Component.Builder
interface Builder {
MyComponent build();
Builder backendModule(BackendModule bm);
Builder frontendModule(FrontendModule fm);
}
}
Upvotes: 48
Views: 35120
Reputation: 114
In my case my module class has a constructor and removing @BindInstance
is the solution.
the module:
@Module
class SomeModule(private val count:Int)
the component builder:
@Component.Builder
interface Builder {
fun engineModule(someModule: SomeModule): Builder
}
Upvotes: 0
Reputation: 7478
Kotlin Answer
Check your constructor of Module.
If you have constructor and application parameter, delete it.
TRUE usage:
@Module
class MyModule {
// This is example module for true usage.
}
••• Wrong usage:
@Module
class MyModule constructor(application: Application) {
// This is example module for wrong usage.
}
Upvotes: 3
Reputation: 181
In my case I was using an object Module, so I had to annotate provider method with @JvmStatic
@Module
object GsonModule {
@JvmStatic
@Singleton
@Provides
fun provideGson() = Gson()
}
Upvotes: 18
Reputation: 21384
I think this provides a somewhat clearer explanation on the use of @BindsInstance
and removal of @Provides Application
, Dagger 2 Component Builder:
@BindsInstance
What?Here’s the definition :
Marks a method on a component builder or subcomponent builder that allows an instance to be bound to some type within the component. — source
WHAAT? I don’t understand it either 😛
Here’s a simple hint of when to use it :
@BindsInstance methods should be preferred to writing a @Module with constructor arguments and immediately providing those values. — source
I come from Spring Boot and Dagger 2 is OMG so much more complicated. :(
So based on my extremely limited experience with Dagger 2, this happens because there a *Module
with a constructor argument which is improperly configured. I still don't know how to properly configure the Module with a constructor argument, but I rather follow recommended approach given by Dagger 2 documentation, and that is to remove the constructor argument(s) and use @BindsInstance
and @Inject
instead.
e.g.
@Module
class NetModule { // no constructor argument here!
@Inject @Named("mqttServer") // replaced by @Inject
internal lateinit var mqttServer: String
}
and in AppComponent
:
@Singleton
@Component(modules = [AndroidSupportInjectionModule::class, AppModule::class, NetModule::class, ActivityBuilder::class])
interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
@BindsInstance // you'll call this when setting up Dagger
fun mqttServer(@Named("mqttServer") mqttServer: String): Builder
fun build(): AppComponent
}
fun inject(app: GeoAssistantApp)
}
Then you provide the dependencies of the modules when constructing the DaggerAppComponent
from the Application
subclass (make sure you specify the subclass name in AndroidManifest.xml
):
class GeoAssistantApp : Application(), HasActivityInjector, HasSupportFragmentInjector {
@Inject
internal lateinit var activityDispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
@Inject
internal lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
override fun onCreate() {
super.onCreate()
Log.i(GeoAssistantApp::class.java.simpleName, "Initializing DaggerAppComponent...")
DaggerAppComponent.builder()
// list of modules/dependencies of modules that are part of this component need to be created here too
.application(this)
.mqttServer(getString(R.string.mqtt_server))
.build()
.inject(this)
}
override fun activityInjector(): AndroidInjector<Activity> {
return activityDispatchingAndroidInjector
}
override fun supportFragmentInjector(): AndroidInjector<Fragment> {
return fragmentDispatchingAndroidInjector
}
}
Note that the support-v4
Fragment
vs native Fragment
usage can be a source of problems. e.g. for support-v4, you need to use AndroidSupportInjectionModule
, HasSupportFragmentInjector
, while with native, you need to use AndroidInjectionModule
, HasFragmentInjector
.
Upvotes: 25
Reputation: 1096
Remove the below code from the AppModule.class and rebuild the project
@Provides
@Singleton
Application provideContext(SomeApplication application) {
return application;
}
Upvotes: 56