I try to call API with Retrofit and Dagger 2 and in my case the DataModel and it's module are injected fine, but not the module of API. I'm sure I miss something, but do not understand what. Here is my Component:
#Singleton
#Component(modules = [SMModule::class, SMNetworkModule::class])
interface SMComponent {
fun inject(fragment: SMListFragment)
}
Modules:
#Module
class SMModule {
#Provides
fun provideSMModel(): SMListDataModel {
return SMListDataModel()
}
}
#Module
object SMNetworkModule {
#JvmStatic
#Singleton
#Provides
fun provideRetrofit(): Retrofit {
val okHttpBuilder = OkHttpClient.Builder()
if (BuildConfig.DEBUG) {
val httpLoggingInterceptor = HttpLoggingInterceptor()
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
okHttpBuilder.addInterceptor(httpLoggingInterceptor)
}
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpBuilder.build())
.build()
}
#JvmStatic
#Singleton
#Provides
fun provideSMInterface(retrofit: Retrofit): SMInterface =
retrofit.create(SMInterface::class.java)
}
DataModel:
class SMListDataModel #Inject constructor() {
#Inject
lateinit var smApi: SMAPI
override fun loadData(): DataResponse {
return smApi.getData().blockingGet()
}
}
my API:
#Singleton
class SMAPI #Inject constructor() {
#Inject
lateinit var smInterface: SMInterface
fun getData(): Single<DataResponse> {
return smInterface.getData()
}
}
and here I inject my Fragment and call DataModel:
#JvmField
#Inject
var dataModel: StocksListDataModel? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DaggerSMComponent.create().inject(this)
}
override fun onResume() {
super.onResume()
val response = dataModel?.loadData()
}
and I get an error:
UninitializedPropertyAccessException: lateinit property smApi has not been initialized
inside of my SMListDataModel.
I looked at this question and there I didn't see the explicit constructor for the API and it works for them. But not for me.
I use this and it works well. (provide Room & Retrofit).
i hope it's be useful
RemoteModule class :
#Module(includes = [AppModule::class])
class RemoteModule {
#Provides
#Singleton
fun provideArticleDatabase(application: App): RoomDataBase? {
return Room.databaseBuilder(
application.applicationContext,
RoomDataBase::class.java,
"fandogh"
)
.build()
}
#Provides
fun provideArticleDao(#Nullable articleDatabase: RoomDataBase): ILocalDataSource? {
return articleDatabase.roomDao()
}
#Provides
#ApplicationScope
fun getApiInterface(retroFit: Retrofit): ApiService {
return retroFit.create(ApiService::class.java)
}
#Provides
#ApplicationScope
fun getRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
// .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build()
}
#Provides
#ApplicationScope
fun getOkHttpCleint(httpLoggingInterceptor: HttpLoggingInterceptor, myAuthHeaderInterceptor: MyAuthHeaderInterceptor): OkHttpClient {
return OkHttpClient.Builder()
.readTimeout(30, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.callTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
// .addInterceptor {
// var request = it.request().newBuilder().addHeader("authorization", Constants.AUTHORIZATION_HEADER).build()
// return#addInterceptor it.proceed(request)
// }
.addInterceptor(myAuthHeaderInterceptor)
.addInterceptor(httpLoggingInterceptor)
.build()
}
#Provides
#ApplicationScope
fun getHttpLoggingInterceptor(): HttpLoggingInterceptor {
val httpLoggingInterceptor = HttpLoggingInterceptor()
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
return httpLoggingInterceptor
}
#Singleton
#Provides
fun getAuthHeaderInterceptor(sharedPrefrences: SharedPreferences): MyAuthHeaderInterceptor {
return MyAuthHeaderInterceptor(sharedPrefrences)
}
}
ViewModelModule :
#Module
abstract class ViewModelModule {
#Binds
abstract fun bindViewModelFactory(factory: DaggerViewModelFactory): ViewModelProvider.Factory // this needs to be only one for whole app (therefore marked as `#Singleton`)
#Binds
#IntoMap
#ViewModelKey(LoginViewModel::class)
abstract fun loginViewModel(viewModel: LoginViewModel): ViewModel
#Binds
#IntoMap
#ViewModelKey(ActMainViewModel::class)
abstract fun mainActivityViewModel(viewModel: ActMainViewModel): ViewModel
}
FragmentBuilder:
#Module
abstract class FragmentBuilder {
#FragmentScope
#ContributesAndroidInjector
abstract fun homeFragment(): HomeFragment?
}
ActivityBuilder :
#Module
abstract class ActivityBuilder {
#ActivityScope
#ContributesAndroidInjector
abstract fun loginActivity(): ActivityLogin?
#ActivityScope
#ContributesAndroidInjector
abstract fun mainActivity(): MainActivity?
}
AppModule :
#Module
abstract class AppModule {
#Binds
#Singleton
abstract fun application(app: App?): Application?
}
ActivityScope :
#Scope
#Retention(value = AnnotationRetention.RUNTIME)
annotation class ActivityScope
FragmentScope :
#Scope
#Retention(value = AnnotationRetention.RUNTIME)
annotation class FragmentScope {
}
AppComponent :
#Singleton
#ApplicationScope
#Component(
modules = [AppModule::class, AndroidSupportInjectionModule::class, RemoteModule::class, ActivityBuilder::class,
FragmentBuilder::class, ViewModelModule::class]
)
interface AppComponent : AndroidInjector<App> {
fun inject(membersFragment: MembersFragment)
override fun inject(myApplication: App)
fun inject(instance: DaggerApplication)
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: App): Builder
fun build(): AppComponent
}
}
Application :
class App : DaggerApplication() {
var appComponent: AppComponent? = null
override fun applicationInjector(): AppComponent {
appComponent = DaggerAppComponent.builder().application(this).build()
appComponent!!.inject(this)
return appComponent!!
}
}
and used in ViewModel :
class LoanViewModel #Inject constructor() : ViewModel() {
#Inject
lateinit var apiService: ApiService
}
Related
I am converting one my project into kotlin source code.
While building the dagger I am encountered with this problem
cannot be provided without an #Inject constructor or an #Provides-annotated method.
I have 2 modules as below
#Module
class AppClient {
#Provides
#Singleton
fun provideHttpCache(application: Application): Cache {
val cacheSize = 10 * 1024 * 1024
return Cache(application.cacheDir, cacheSize.toLong())
}
#Provides
#Singleton
fun provideGson(): Gson {
val gsonBuilder = GsonBuilder()
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
// gsonBuilder.excludeFieldsWithoutExposeAnnotation();
return gsonBuilder.create()
}
#Provides
#Singleton
fun provideOkhttpClient(cache: Cache): OkHttpClient {
val interceptor = HttpLoggingInterceptor()
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
val client = OkHttpClient.Builder()
client.cache(cache)
client.addInterceptor(interceptor)
return client.build()
}
#Provides
#Singleton
fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(NetworkConstant.BASE_URL)
.client(okHttpClient)
.build()
}
#Provides
#Singleton
fun provideApiCall(retrofit: Retrofit): NetworkCall {
return retrofit.create(NetworkCall::class.java)
}
#Provides
#Singleton
fun provideSharedPreference(application: Application): SharedPreferences {
return application.applicationContext.getSharedPreferences(
application.getString(R.string.shared_pref_name),
MODE_PRIVATE
)
}
#Provides
#Singleton
fun provideSharedPreferenceEditor(sharedPreferences: SharedPreferences): SharedPreferences.Editor {
return sharedPreferences.edit()
}
#Provides
#Singleton
fun provideAppPresenter(
sharedPreferences: SharedPreferences, editor: SharedPreferences.Editor,
apiCall: NetworkCall): AppPresenter {
return AppPresenter(sharedPreferences, editor, apiCall)
}
}
And the second module
#Module
class AppModule(val application: MyApplication) {
#Provides
#Singleton
internal fun provideApplication(): MyApplication {
return application
}
}
Application class
class MyApplication : Application() {
lateinit var mApiComponent: AppComponent
override fun onCreate() {
super.onCreate()
mApiComponent = DaggerAppComponent.builder()
.appModule(AppModule(this))
.appClient(AppClient())
.build()
}
fun getAppComponent(): AppComponent {
return mApiComponent
}
}
And the component interface
#Singleton
#Component(modules = [AppModule::class, AppClient::class])
interface AppComponent {
fun inject(activity: LoginActivity)
}
Can someone help out as to what's wrong here?
It seems I was passing the wrong application class. So silly of me
I'm working in a project and I need to inject Retrofit object with Dagger 2. I search info but I only have been able to do a few steps and now I don't know how to continue:
My component:
#Singleton
#Component(modules = arrayOf(NetworkModule::class))
interface NetworkComponent {
fun inject(foo: TheApplication)
}
My module:
#Module
class NetworkModule {
#Provides
#Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.chucknorris.io/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
}
}
And now I see I have to make a Class who extends from Application for init the Component and make an #Inject next:
class TheApplication: Application() {
override fun onCreate() {
super.onCreate()
val net: NetworkModule = Dagger...
}
}
Theoretically when I put the Dagger... it should be DaggerNetworkComponent but I rebuild project and still missing.
Anyone can explain to me for what is the Application.class made for and how I can continue?
Try this
AppComponent.kt
#Component(modules = [NetworkModule::class])
#Singleton
interface AppComponent {
fun inject(app: MyApp)
}
NetworkModule.kt
#Module
class NetworkModule {
#Singleton
#Provides
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("YOUR_BASE_URL")
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
}
#Singleton
#Provides
fun provideApi(retrofit: Retrofit): WebApi {
return retrofit.create(WebApi::class.java)
}
#Singleton
#Provides
fun provideOkHttpClient(
interceptors: ArrayList<Interceptor>
): OkHttpClient {
val clientBuilder = OkHttpClient.Builder()
.followRedirects(false)
interceptors.forEach {
clientBuilder.addInterceptor(it)
}
return clientBuilder.build()
}
#Singleton
#Provides
fun provideInterceptors(): ArrayList<Interceptor> {
val interceptors = arrayListOf<Interceptor>()
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) {
HttpLoggingInterceptor.Level.BODY
} else {
HttpLoggingInterceptor.Level.NONE
}
}
interceptors.add(loggingInterceptor)
return interceptors
}
}
MyApp.kt
class MyApp : Application() {
companion object {
lateinit var instance: MyApp
private set
}
lateinit var appComponent: AppComponent
private set
override fun onCreate() {
super.onCreate()
instance = this
initComponent()
}
private fun initComponent() {
appComponent = DaggerAppComponent.builder()
.build()
appComponent.inject(this)
}
}
AndroidManifest.xml
<application
android:name=".MyApp"
....
I am newbie in dependency injection with Dagger in Android
I have this error Unable to start activity ComponentInfo{MainActivity}: kotlin.UninitializedPropertyAccessException: lateinit property dispatchingAndroidInjector has not been initialized
I can't know what is the exact error in my code, Should I change something ? Although in another project I work on, they have the same code except AndroidInjection.inject(this) and the code is working perfectly
Thanks a lot for your help
Here is my files:
AppComponent
#Singleton
#Component(
modules = [AndroidSupportInjectionModule::class,
AppModule::class, NetworkModule::class,
ActivityBuilder::class]
)
interface AppComponent : AndroidInjector<Application> {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
}
AppModule
#Module(includes = [ViewModelModule::class])
class AppModule {
#Provides
fun provideContext(application: MyApplication): Context {
return application.applicationContext
}
#Provides
fun provideHandler(): Handler {
return Handler()
}
#Provides
#Singleton
fun provideSharedPreferences(context: Context): SharedPreferences {
return context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
}
#Provides
#Singleton
fun provideSharedPreferenceUtils(context: Context): SharedPreferenceUtils {
return SharedPreferenceUtils(provideSharedPreferences(context))
}
}
ActivityBuilder
#Module
abstract class ActivityBuilder {
#ContributesAndroidInjector
abstract fun bindMainActivity(): MainActivity
}
NetworkModule
#Module(includes = [AppModule::class])
// Safe here as we are dealing with a Dagger 2 module
#Suppress("unused")
class NetworkModule {
#Provides
#Singleton
fun provideCache(context: Context): Cache {
return Cache(context.cacheDir, CACHE_SIZE)
}
#Provides
#Singleton
fun provideOkHttpClient(cache: Cache, context: Context): OkHttpClient {
return OkHttpClient.Builder()
.cache(cache)
.addInterceptor { chain ->
var request = chain.request()
request = if (hasNetwork(context)!!)
request.newBuilder().header("Cache-Control", "public, max-age=" + 5).build()
else
request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build()
chain.proceed(request)
}
.build()
}
/**
* Provides the Quotes service implementation.
* #param retrofit the Retrofit object used to instantiate the service
* #return the Quote service implementation.
*/
#Provides
#Singleton
fun provideQuotesAPI(retrofit: Retrofit): QuotesAPI {
return retrofit.create(QuotesAPI::class.java)
}
/**
* Provides the Retrofit object.
* #return the Retrofit object
*/
#Provides
#Singleton
fun provideRetrofitInterface(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(MoshiConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.client(okHttpClient)
.build()
}
}
ViewModelModule
#Module
abstract class ViewModelModule {
#Binds
abstract fun bindViewModelFactory(factory: MyViewModelFactory): ViewModelProvider.Factory
#Binds
#IntoMap
#ViewModelKey(QuotesListViewModel::class)
internal abstract fun bindsQuotesListViewModel(quotesListViewModel: QuotesListViewModel): ViewModel
#Binds
#IntoMap
#ViewModelKey(QuoteListItemViewModel::class)
internal abstract fun bindsQuoteListItemViewModel(quoteListItemViewModel: QuoteListItemViewModel): ViewModel
}
MyApplication
class MyApplication : Application(), HasActivityInjector {
#Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
override fun activityInjector(): AndroidInjector<Activity> = dispatchingAndroidInjector
override fun onCreate() {
super.onCreate()
// StateSaver.setEnabledForAllActivitiesAndSupportFragments(this, true)
// initialise dependency injection
DaggerAppComponent
.builder()
.application(this)
.build()
.inject(this)
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
}
MainActivity
class MainActivity : DaggerAppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
private lateinit var binding: ActivityMainBinding
private lateinit var menu: Menu
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
}
}
Finally, after several attempts, I found my error, in AppComponent
I should call MyApplication class and not Application
#Singleton
#Component(
modules = [AndroidSupportInjectionModule::class,
AppModule::class, NetworkModule::class,
ActivityBuilder::class]
)
interface AppComponent : AndroidInjector<MyApplication> {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: MyApplication): Builder
fun build(): AppComponent
}
I've started using Dagger 2 with Android Injector and faced an issue
I have 5 modules, that are composed into one component
#Singleton
#Component(modules = [AndroidInjectionModule::class,
ActivityBuilder::class,
AndroidSupportInjectionModule::class
, ApplicationModule::class,NetworkModule::class])
interface ApplicationComponent {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application): Builder
fun build(): ApplicationComponent
}
fun inject(app: DeliveryApplication)
fun service(): DeliveryApi
}
Network Module look like
#Module
class NetworkModule {
#Singleton
#Provides
fun providesDeliveryApi(retrofit: Retrofit):DeliveryApi = retrofit.create(DeliveryApi::class.java)
#Singleton
#Provides
fun providesRetrofit(okHttpClient: OkHttpClient):Retrofit =
Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()
#Singleton
#Provides
fun providesOkHttpClient(context:Context): OkHttpClient {
/* val logging = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}*/
val cacheSize = (5 * 1024 * 1024).toLong()
val myCache = Cache(context.cacheDir, cacheSize)
val okHttpClient = OkHttpClient.Builder()
.cache(myCache)
.addInterceptor { chain ->
var request = chain.request()
request = if (hasNetwork(context)!!)
// setting 5 Mb Cabacity
request.newBuilder().header("Cache-Control", "public, max-age=" + 5).build()
else
request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build()
chain.proceed(request)
}
.build()
return okHttpClient
}
#Singleton
#Provides
fun provideImageLoader(context: Context) : ImageLoader {
return PicassoImageLoader(Picasso.with(context))
}
application Module look like
const val SCHEDULER_MAIN_THREAD = "mainThread"
const val SCHEDULER_IO = "io"
#Module
class ApplicationModule {
#Provides
#Named(SCHEDULER_MAIN_THREAD)
fun provideAndroidMainThreadScheduler() : Scheduler = AndroidSchedulers.mainThread()
#Provides
#Named(SCHEDULER_IO)
fun provideIoScheduler() : Scheduler = Schedulers.io()
#Provides
#Singleton
fun provideContext(application: Application): Context {
return application
}
}
ActivityBuilder is pretty simple: just combination of modules for Activities
and FragmentsModule for fragments
#Module
abstract class ActivityBuilder {
#PerActivity
#ContributesAndroidInjector(modules = [FragmentsModule::class, DeliveriesModule::class])
abstract fun bindMainActivity(): DeliveriesActivity
#PerActivity
#ContributesAndroidInjector(modules = [FragmentsModule::class, DeliveriesDetailsModule::class])
abstract fun bindDeliveryDetailsActivity(): DeliveryDetailsActivity
}
#Module
abstract class FragmentsModule {
#ContributesAndroidInjector
abstract fun provideDeliveriesListFragment(): DeliveriesListFragment
#ContributesAndroidInjector
abstract fun provideDeliveryDetailsFragment(): DeliveryDetailsFragment
}
Delivery Module which used to provide all instances of the DeliveryActivity
#Module
class DeliveriesModule {
#Provides
#PerActivity
fun providesDeliveryRepository(deliveryApi: DeliveryApi): DeliveryRepository {
return DeliveryDownloader(deliveryApi)
}
#Provides
#PerActivity
fun providesDeliveryListUseCases(deliveryRepository: DeliveryRepository): DeliveryListUseCase {
return DeliveryListInteractor(deliveryRepository)
}
#Provides
#PerActivity
fun provideDeliveriesListFragment(): DeliveriesListFragment {
return DeliveriesListFragment()
}
}
ViewModelFactory where the problem here, the compiler says that DeliveryListUseCase cannot be provided without an #Provides-annotated method
class ViewModelFactory #Inject constructor(private val application: Application,
#Named(SCHEDULER_IO) val subscribeOnScheduler: Scheduler,
#Named(SCHEDULER_MAIN_THREAD) val observeOnScheduler: Scheduler,
private val deliveryListUseCase: DeliveryListUseCase) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return when {
modelClass.isAssignableFrom(DeliveryListViewModel::class.java) ->
DeliveryListViewModel(application,deliveryListUseCase,subscribeOnScheduler,observeOnScheduler) as T
else -> BaseViewModel(application) as T
}
}
}
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
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.
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();
}