Bryan Bryan - 3 months ago 15
Android Question

Cannot be Provided Without an @Provides-annotated Method

There have been many other similar questions, but none of the answers have been applicable to my code. I cannot figure out what I have done wrong.

First I have a

NetworkModule
that is used as a module for the
ApplicationComponent
:

@Module
open class NetworkModule {

companion object {
private val BASE = "http://www.example.com/"
}

@Provides @ApplicationScope
fun provideClient(): OkHttpClient = OkHttpClient()

@Provides @ApplicationScope
fun provideMoshi(): Moshi {
return Moshi.Builder().add(InstantAdapter).add(UriAdapter).build()
}

@Provides @ApplicationScope
fun provideRetrofit(client: OkHttpClient, moshi: Moshi): Retrofit {
return Retrofit.Builder().client(client).baseUrl(BASE)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
}

@Provides @ApplicationScope
fun provideArticleService(retrofit: Retrofit): ArticleService {
return retrofit.create(ArticleService::class.java)
}

}





@ApplicationScope @Component(modules = arrayOf(ContextModule::class, RealmModule::class, NetworkModule::class))
interface ApplicationComponent {}


Then the
ApplicationComponent
is built in my
Application
class:

class MyApplication : Application() {

override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)

plantLog()
drawDagger()
}

private fun drawDagger() {
Injector.initializeApplicationComponent(this)
}

// ...

}





object Injector {

lateinit var applicationComponent: ApplicationComponent
private set

fun initializeApplicationComponent(context: Context) {
applicationComponent = DaggerApplicationComponent.builder()
.contextModule(ContextModule(context))
.networkModule(NetworkModule())
.realmModule(RealmModule())
.build()
}

// ...

}


Then I have an
ActivityModule
that is used in the
ActivityComponent
(which has
ApplicationComponent
as a dependency):

@Module
open class ActivityModule(private val activity: AppCompatActivity) {

@Provides @ActivityScope @ActivityContext
fun provideContext(): Context = activity

@Provides @ActivityScope
fun provideFragmentManager(): FragmentManager = activity.supportFragmentManager

}





@ActivityScope @Component(dependencies = arrayOf(ApplicationComponent::class), modules = arrayOf(ActivityModule::class))
interface ActivityComponent {

fun inject(activity: MainActivity)

}


Finally, I create a new
ActivityComponent
in the
MainActivity
and
@Inject
the
ArticleService
:

class MainActivity : AppCompatActivity() {

@Inject lateinit var service: ArticleService

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

DaggerActivityComponent.builder()
.applicationComponent(Injector.applicationComponent)
.activityModule(ActivityModule(this))
.build().inject(this)

service.getNewsArticles()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.newThread())
.subscribe(
{ response -> onNext(response) },
{ error -> onError(error) })
}

// ...

}


But when I try to build I get the following error, even though I believe the
provideArticleService()
function in
NetworkModule
is annotated correctly:


ArticleService cannot be provided without an @Provides- or
@Produces-annotated method.

Answer

You're missing the provision methods to inherit to your Activity scoped component. Either use subcomponents instead of component dependency, or define the provision methods in your application component.

 @ApplicationScope @Component(modules = arrayOf(ContextModule::class, RealmModule::class, NetworkModule::class))
 interface ApplicationComponent {
      ArticleService articleService();
 }
Comments