I've been trying to resolve my issue but I can't find anything...
MyAppApplication.kt :
#HiltAndroidApp
class MyAppApplication : Application()
MainActivity.kt
#AndroidEntryPoint
class MainActivity: AppCompatActivity()
MyViewModel.kt
#HiltViewModel
class MyViewModel #Inject constructor(private val myRepository: MyRepository,
private val appPreference: AppPreference) : ViewModel(){}
MyRepository.kt
interface MyRepository {
fun test()
}
class MyRepositoryImpl #Inject constructor(private val service:Service): MyRepository {
override fun test() { print("") }
}
HiltModule.kt
#Module
#InstallIn(SingletonComponent::class)
object NetworkModule {
private const val BASE_URL = "..."
#Singleton
#Provides
fun getGsonConverterFactory(): GsonConverterFactory = GsonConverterFactory.create(
GsonBuilder()
.setLenient()
.create()
)
#Singleton
#Provides
fun getRetrofit(gsonConverterFactory: GsonConverterFactory): Retrofit =
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(gsonConverterFactory)
.build()
#Singleton
#Provides
fun provideService(retrofitClient: Retrofit) = retrofitClient.create(Service::class.java)
#Singleton
#Provides
fun getAppPreference(application: Application) :AppPreference = AppPreferenceImpl(application)
}
#Module
#InstallIn(ViewModelComponent::class)
object RepositoryModule {
#ViewModelScoped
#Provides
fun getMyRepository(myRepository: MyRepositoryImpl): MyRepository = myRepository
}
failed with 2 errors
[Dagger/MissingBinding] com.example.app.repository.MyRepositoryImpl cannot be provided without an #Inject constructor or an #Provides-annotated method.
com.example.myapp.repository.MyRepositoryImmpl is injected at....
java.lang.reflect.InvocationTargetException (no error message)
Do you have any idea of what I am missing?
Thanks you!
Complementary informations:
I have tried switching ViewModelScope to Singleton.
I have tried switching Object RepositoryModule to
#Module
#InstallIn(ViewModelComponent::class)
abstract class RepositoryModule {
#Binds
#ViewModelScoped
abstract fun bindMyRepository(myRepository: MyRepositoryImpl): MyRepository
}
I have tried having them all inside One HiltModule Object
I have tried
#Module
#InstallIn(SingletonComponent::class)
object RepositoryModule {
#Provides
fun getMyRepository(service: Service): MyRepository = MyRepositoryImpl(service)
}
But same issue mentioned.
Related
If I just use the AuthRepository class in a single UseCase it's fine. However, if I try to use it in both AuthUseCase and RefreshTokenUseCase as in the example, I get an error.
Any suggestions other than using Lazy<> ?
Any help will be appreciated.
-
Error
-
App_HiltComponents.java:139: error: [Dagger/DependencyCycle] Found a dependency cycle:
public abstract static class SingletonC implements App_GeneratedInjector,
^
AppRepository is injected at
RefreshTokenTokenUseCase(authRepository)
RefreshTokenTokenUseCase is injected at
AppAuthenticator(refreshTokenTokenUseCase)
......
...
..
AuthUseCase(authRepository)
AuthUseCase is injected at
MainViewModel(authUseCase, …)
MainViewModel is injected at
MainViewModel_HiltModules.BindsModule.binds(vm)
My Code
-
#Module
#InstallIn(SingletonComponent::class)
object NetworkModule {
#Singleton
#Provides
fun provideRetrofit(): Retrofit =
Retrofit.Builder()
.baseUrl(Data.url)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
#Module
#InstallIn(SingletonComponent::class)
object ApiModule {
#Singleton
#Provides
fun provideAuthAPI(
retrofit: Retrofit
): AuthAPI = retrofit.create(AuthAPI::class.java)
}
#Singleton
class AuthRepository #Inject constructor(
private var authAPI: AuthAPI,
) {
}
#Singleton
class AuthUseCase #Inject constructor(
private val authRepository: AuthRepository
) : UseCase<Response?, AuthUseCase.Params>() {
}
#Singleton
class RefreshTokenUseCase #Inject constructor(
private val authRepository: AuthRepository
) : UseCase<String?, RefreshTokenUseCase.Params>() {
}
You can use Provider<T> instead of Lazy and than call .get() on it.
#Singleton
class RefreshTokenUseCase #Inject constructor(
private val authRepositoryProvider: Provider<AuthRepository>
) : UseCase<String?, RefreshTokenUseCase.Params>() {
fun getRefreshToken() = authRepositoryProvider.get().getRefreshToken() //example of usage
}
This means RefreshTokenUseCase will be created before AuthRepository is created and later on it will receive singleton AuthRepository instance it needs.
For more complete explanation check this SO post.
I trying on Hilt codelab
https://codelabs.developers.google.com/codelabs/android-hilt#10
It's working fine with Activity and Fragment
logger is a RoomDB
Then I try to inject logger into viewModel with this article
By add
implementation "androidx.hilt:hilt-lifecycle-viewmodel
:1.0.0-alpha02"
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
ViewModelCode
class RecordFragmentViewModel #ViewModelInject constructor(#Assisted private val savedStateHandle: SavedStateHandle) :
ViewModel() {
#DatabaseLogger
#Inject
lateinit var logger: LoggerDataSource
Class logger to inject
class LoggerLocalDataSource
#Inject constructor(private val logDao: LogDao) : LoggerDataSource {
LoggingModule
#Qualifier
annotation class InMemoryLogger
#Qualifier
annotation class DatabaseLogger
#InstallIn(ApplicationComponent::class)
#Module
abstract class LoggingDatabaseModule {
#DatabaseLogger
#Singleton
#Binds
abstract fun bindDatabaseLogger(impl: LoggerLocalDataSource): LoggerDataSource
}
#InstallIn(ActivityComponent::class)
#Module
abstract class LoggingInMemoryModule {
#InMemoryLogger
#ActivityScoped
#Binds
abstract fun bindInMemoryLogger(impl: LoggerInMemoryDataSource): LoggerDataSource
}
DatabaseModule
#InstallIn(ApplicationComponent::class)
#Module
object DatabaseModule {
#Provides
#Singleton
fun provideDatabase(#ApplicationContext appContext: Context): AppDatabase {
return Room.databaseBuilder(
appContext,
AppDatabase::class.java,
"logging.db"
).build()
}
#Provides
fun provideLogDao(database: AppDatabase): LogDao {
return database.logDao()
}
}
It's compile and run without error.
However, I use debug to watch logger and its got.
Method threw 'kotlin.UninitializedPropertyAccessException' exception.
I call logger.something() at run time its throw
Fatal Exception: kotlin.UninitializedPropertyAccessException
lateinit property logger has not been initialized
More info
https://dagger.dev/hilt/migration-guide.html
https://codelabs.developers.google.com/codelabs/android-hilt#10
https://medium.com/mobile-app-development-publication/injecting-viewmodel-with-dagger-hilt-54ca2e433865
Since LoggerDataSource is a interface we need to specify which implementation we need to inject. Thanks to #Andrew for the idea of inject to constructor
class RecordFragmentViewModel
#ViewModelInject
constructor(#Assisted private val savedStateHandle: SavedStateHandle,
#DatabaseLogger private val logger: LoggerDataSource) :
ViewModel(), LifecycleObserver {
To specify
#Qualifier
annotation class InMemoryLogger
#Qualifier
annotation class DatabaseLogger
#InstallIn(ApplicationComponent::class)
#Module
abstract class LoggingDatabaseModule {
#DatabaseLogger
#Singleton
#Binds
abstract fun bindDatabaseLogger(impl: LoggerLocalDataSource): LoggerDataSource
}
#InstallIn(ActivityComponent::class)
#Module
abstract class LoggingInMemoryModule {
#InMemoryLogger
#ActivityScoped
#Binds
abstract fun bindInMemoryLogger(impl: LoggerInMemoryDataSource): LoggerDataSource
}
I've just refactored my dagger code to make it scalable and move all core stuff to a separate module called di.
Now when I try to inject my dependencies in the app module I got this :
[Dagger/MissingBinding] retrofit2.Retrofit cannot be provided without an #Inject constructor or an #Provides-annotated method.
public abstract interface ResetPasswordComponent {
^
retrofit2.Retrofit is injected at
com.sahra.oms.ibshop.features.resetpassword.di.ResetPasswordNetworkModule.providerResetPasswordAPI(retrofit)
com.sahra.oms.ibshop.data.remote.service.ResetPasswordService is injected at
com.sahra.oms.ibshop.data.repisotory.nationalid.UniqueRepositoryImpl(resetPasswordService)
com.sahra.oms.ibshop.data.repisotory.nationalid.UniqueRepositoryImpl is injected at
com.sahra.oms.ibshop.features.resetpassword.di.ResetPasswordModule.bindUniqueIdRepository(uniqueRepositoryImpl)
com.sahra.oms.ibshop.data.repisotory.nationalid.UniqueIdRepository is injected at
com.sahra.oms.ibshop.features.resetpassword.uniqueid.CheckUniqueIDViewModel(repository)
com.sahra.oms.ibshop.features.resetpassword.uniqueid.CheckUniqueIDViewModel is injected at
com.sahra.oms.ibshop.features.resetpassword.di.ResetPasswordModule.bindCheckIdViewModel(checkUniqueIDViewModel)
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.sahra.oms.ibishop.di.util.ViewModelFactory(viewModelsMap)
com.sahra.oms.ibishop.di.util.ViewModelFactory is injected at
com.sahra.oms.ibshop.di.ViewModelBuilder.bindViewModelFactory(arg0)
androidx.lifecycle.ViewModelProvider.Factory is injected at
com.sahra.oms.ibshop.features.resetpassword.newpassword.NewPasswordFragment.viewModelFactory
com.sahra.oms.ibshop.features.resetpassword.newpassword.NewPasswordFragment is injected at
com.sahra.oms.ibshop.features.resetpassword.di.ResetPasswordComponent.inject(com.sahra.oms.ibshop.features.resetpassword.newpassword.NewPasswordFragment)
ResetPasswordService is just a Retrofit interface.
Here is my code:
AppComponent
#Singleton
#AppScope
#Component
interface AppComponent {
fun provideContextComponent(): ContextComponent
fun provideNetworkComponent(): NetworkComponent
fun provideSharedPrefComponent(): SharedPreferencesComponent
fun inject(app: Application)
#Component.Factory
interface Factory {
fun create(
#BindsInstance
context: ContextComponent,
#BindsInstance
network: NetworkComponent,
#BindsInstance
sharedPrefs: SharedPreferencesComponent
): AppComponent
}
}
NetworkComponent :
#Scope
#Retention(AnnotationRetention.RUNTIME)
annotation class NetworkScope
#NetworkScope
#Component(
dependencies = [ContextComponent::class],
modules = [OkHttpModule::class, AuthBinderModule::class]
)
interface NetworkComponent {
fun provideOkHttp(): OkHttpClient
fun provideRetrofit(): Retrofit
fun provideGson(): GsonConverterFactory
}
OkHttpModule :
#Module
object OkHttpModule {
private const val BASE_URL = "base_url"
#Provides
#JvmStatic
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor(
HttpLoggingInterceptor.Logger { message -> Log.d("<<<network>>>", message) }).apply {
level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
}
}
#Provides
#JvmStatic
fun provideChuckInterceptor(app: Application): ChuckInterceptor = ChuckInterceptor(app)
#Provides
#JvmStatic
fun provideOkhttpCache(app: Application): Cache =
Cache(app.cacheDir, 50_000_000)
#Provides
#NetworkScope
#JvmStatic
fun provideClient(
loggingInterceptor: HttpLoggingInterceptor,
chuckInterceptor: ChuckInterceptor,
authInterceptor: Interceptor,
cache: Cache
): OkHttpClient {
return OkHttpClient.Builder()
.cache(cache)
.addInterceptor(loggingInterceptor)
.addInterceptor(authInterceptor)
.addInterceptor(chuckInterceptor)
.build()
}
#Provides
#NetworkScope
#JvmStatic
fun provideGson() = Gson()
#Provides
#JvmStatic
fun provideGsonConverter(gson: Gson) = GsonConverterFactory.create(gson)
#Provides
#NetworkScope
#JvmStatic
fun provideRetrofit(
gsonConverterFactory: GsonConverterFactory,
client: Lazy<OkHttpClient>
): Retrofit = Retrofit.Builder()
.callFactory { request -> client.get().newCall(request) }
.baseUrl(BASE_URL)
.addConverterFactory(gsonConverterFactory)
.build()
}
Here is how I try to inject the dependencies:
#FeatureScope
#Component(
dependencies = [AppComponent::class],
modules = [
ResetPasswordNetworkModule::class,
ResetPasswordModule::class,
ViewModelBuilder::class
]
)
interface ResetPasswordComponent {
fun inject(newPasswordFragment: NewPasswordFragment)
fun inject(checkUniqueIDFragment: CheckUniqueIDFragment)
#Component.Builder
interface Builder {
fun coreComponent(appComponent: AppComponent): Builder
fun build(): ResetPasswordComponent
}
}
#Module
abstract class ResetPasswordModule {
#Binds
abstract fun bindResetPasswordRepository(resetPasswordRepositoryImpl: ResetPasswordRepositoryImpl): ResetPasswordRepository
#Binds
abstract fun bindUniqueIdRepository(uniqueRepositoryImpl: UniqueRepositoryImpl): UniqueIdRepository
#Binds
#IntoMap
#ViewModelKey(CheckUniqueIDViewModel::class)
abstract fun bindCheckIdViewModel(checkUniqueIDViewModel: CheckUniqueIDViewModel): ViewModel
#Binds
#IntoMap
#ViewModelKey(NewPasswordViewModel::class)
abstract fun bindNewPasswordViewModel(newPasswordViewModel: NewPasswordViewModel): ViewModel
}
#Module
object ResetPasswordNetworkModule {
#Provides
#JvmStatic
#FeatureScope
fun provideUserAPI(
retrofit: Retrofit
): ResetPasswordService = retrofit.create(ResetPasswordService::class.java)
}
and here is my repository code:
class ResetPasswordRepositoryImpl #Inject constructor(
private val resetPasswordService: ResetPasswordService
) : ResetPasswordRepository {
}
Fragment :
class NewPasswordFragment{
#Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
}
class NewPasswordViewModel #Inject constructor(
private val repository: ResetPasswordRepository
)
Thanks in advance.
Your app component factory looks like this:
fun create(
#BindsInstance
context: ContextComponent,
#BindsInstance
network: NetworkComponent,
#BindsInstance
sharedPrefs: SharedPreferencesComponent
): AppComponent
This provides access to an instance of NetworkComponent, so any #Provides, #Binds, or #Inject that requires a NetworkComponent can get one. It does not, however, give direct access to NetworkComponent's object graph.
NetworkComponent already exposes Retrofit, so you can certainly get one if you have access to the component. However, this process is not automatic, and in your setting requires a #Provides method.
#Provides
fun provideRetrofit(component: NetworkComponent): Retrofit = component.provideRetrofit()
This is more convoluted that it needs to be. A better way to accomplish this is to make NetworkComponent a dependency of AppComponent (or just use its modules and drop the network component entirely), then expose Retrofit in AppComponent.
// using multiple scoped dependencies requires Dagger 2.27
#AppScope
#Component(dependencies = [ContextComponent::class, NetworkComponent::class, SharedPreferencesComponent::class])
interface AppComponent {
fun provideRetrofit(): Retrofit
// ...
}
I have gone through all the answers with the above title but couldn't find the solution. Basically I want to do scoping. I want to inject ApiService only to HomeViewModel. It should not be available to LoginViewModel. I have my following setup and the error which I am getting:
Info: If I remove the provideLoginActivity() from ActivityModule everything works fine. Why behaving like that?
AppComponent:
#Singleton
#Component(
modules = [AndroidInjectionModule::class, ActivityModule::class, AppModule::class]
)
interface AppComponent : AndroidInjector<BaseApplication> {
#Component.Factory
interface Factory {
fun application(#BindsInstance baseApplication: BaseApplication): AppComponent
}
}
AppModule:
#Module
object AppModule {
#Singleton
#JvmStatic
#Provides
fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://jsonplaceholder.typicode.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
}
ActivityModule:
#Module
abstract class ActivityModule {
#ContributesAndroidInjector(modules = [ViewModelBuilder::class, NetworkModule::class])
internal abstract fun getHomeActivity(): HomeActivity
#ContributesAndroidInjector(modules = [ViewModelBuilder::class])
internal abstract fun provideLoginActivity(): LoginActivity
#Binds
#IntoMap
#ViewModelKey(LoginViewModel::class)
abstract fun bindLoginViewModel(loginViewModel: LoginViewModel): ViewModel
#Binds
#IntoMap
#ViewModelKey(HomeViewModel::class)
abstract fun bindHomeViewModel(homeViewModel: HomeViewModel): ViewModel
}
NetworkModule:
#Module
object NetworkModule {
#JvmStatic
#Provides
fun getApiService(retrofit: Retrofit): ApiService {
return retrofit.create(ApiService::class.java)
}
}
ViewModelFactory:
class ViewModelFactory #Inject constructor(
private val creators: #JvmSuppressWildcards Map<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
var creator: Provider<out ViewModel>? = creators[modelClass]
if (creator == null) {
for ((key, value) in creators) {
if (modelClass.isAssignableFrom(key)) {
creator = value
break
}
}
}
if (creator == null) {
throw IllegalArgumentException("Unknown model class: $modelClass")
}
try {
#Suppress("UNCHECKED_CAST")
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
#Module
internal abstract class ViewModelBuilder {
#Binds
internal abstract fun bindViewModelFactory(
factory: ViewModelFactory
): ViewModelProvider.Factory
}
#Target(
AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER
)
#Retention(AnnotationRetention.RUNTIME)
#MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
HomeViewModel:
class HomeViewModel #Inject constructor(private val apiService: ApiService) : ViewModel() {
val todoLiveData: LiveData<Todo> = liveData(Dispatchers.IO) {
val response: Todo = apiService.getTodo(1)
emit(response)
}
}
Error:
error: [Dagger/MissingBinding] com.sagar.daggertest.repository.network.ApiService cannot be provided without an #Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.sagar.daggertest.BaseApplication> {
^
A binding with matching key exists in component: com.sagar.daggertest.di.HomeActivityModule_GetHomeActivity$app_debug.HomeActivitySubcomponent
com.sagar.daggertest.repository.network.ApiService is injected at
com.sagar.daggertest.HomeViewModel(apiService)
com.sagar.daggertest.HomeViewModel is injected at
com.sagar.daggertest.di.HomeActivityModule.bindHomeViewModel(homeViewModel)
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.sagar.daggertest.di.ViewModelFactory(creators)
com.sagar.daggertest.di.ViewModelFactory is injected at
com.sagar.daggertest.di.ViewModelBuilder.bindViewModelFactory$app_debug(factory)
androidx.lifecycle.ViewModelProvider.Factory is injected at
com.sagar.daggertest.LoginActivity.viewModelFactory
com.sagar.daggertest.LoginActivity is injected at
dagger.android.AndroidInjector.inject(T) [com.sagar.daggertest.di.AppComponent → com.sagar.daggertest.di.HomeActivityModule_ProvideLoginActivity$app_debug.LoginActivitySubcomponent]
#ContributesAndroidInjector creates a subcomponent under the hood ( which is HomeActivityModule_GetHomeActivity$app_debug.HomeActivitySubcomponent in logs ).
In your ActivityModule, you're trying to provide HomeViewModel for map in ViewModelFactory, which is also injected at LoginActivity. But due to HomeViewModel needing ApiService and your ApiService is in NetworkModule which is scoped to subcomponent dagger generated - it fails.
Solution would be moving your multibinding to corresponding scope. By doing so, you're taking HomeViewModel out of map which is injected in LoginActivity, so it won't complain.
You can create a new module, let's say ViewModelModule and put your provider there:
#Module
abstract class ViewModelModule {
#Binds
#IntoMap
#ViewModelKey(HomeViewModel::class)
abstract fun bindHomeViewModel(homeViewModel: HomeViewModel): ViewModel
}
and pass it along with other modules to HomeActivity's contributor:
#ContributesAndroidInjector(modules = [ViewModelBuilder::class, NetworkModule::class, ViewModelModule::class])
internal abstract fun getHomeActivity(): HomeActivity
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();
}