Search code examples
androidkotlindagger-2dagger

Dagger2 + Kotlin: lateinit property appComponent has not been initialized


I'm using Dagger2 to inject class dependent like bellow.

This is a component for Dagger2, AppComponent.kt:

    @Component(modules = [ContextModule::class, SuggestModule::class, RetrofitModule::class,
    TranslateModule::class, DatabaseModule::class, ViewModelModule::class, FragmentModule::class])
interface AppComponent {
    @Singleton
    fun inject(fragment: TranslateFragment)
    @Singleton
    fun inject(fragment: FavouriteFragment)
    @Singleton fun inject(fragment: TensesFragment)
    @Singleton
    fun inject(activity: TensesActivity)
    @Singleton
    fun inject(activity: MainActivity)

    @Singleton
    fun inject(translateViewModel: TranslateViewModel)
    @Singleton
    fun inject(favouriteViewModel: FavouriteViewModel)

    @Singleton
    fun inject(translateProvider: TranslateProvider)
}

This is App class extended Application class, where i built my component , App.kt

class App : Application() {

    companion object{
        lateinit var appComponent: AppComponent
    }

    override fun onCreate() {
        super.onCreate()

        appComponent = DaggerAppComponent.builder()
            .contextModule(ContextModule(this))
            .suggestModule(SuggestModule(this))
            .retrofitModule(RetrofitModule())
            .translateModule(TranslateModule(TranslateProvider()))
            .databaseModule(DatabaseModule(DatabaseManager(this)))
            .viewModelModule(ViewModelModule())
            .fragmentModule(FragmentModule())
            .build()
    }
}

First, i injected TranslateFragment into MainActivity, MainActivity.kt

class MainActivity : AppCompatActivity {

    constructor(){
        App.appComponent.inject(this)
    }

    @Inject
    lateinit var translateFragment: TranslateFragment
}

Second, i injected TranslateViewModel into TranslateFragment, TranslateFragment.kt

class TranslateFragment : Fragment {

    @Inject
    constructor() {
        App.appComponent.inject(this)
    }

    @Inject
    lateinit var translateViewModel: TranslateViewModel
}

Third, i injected TranslateProvider into TranslateViewModel, TranslateViewModel.kt

class TranslateViewModel : BaseObservable {

    @Inject
    constructor() {
        App.appComponent.inject(this)
    }

    @Inject
    lateinit var translateProvider: TranslateProvider
}

End, i injected RetrofitProvider into TranslateProvider, TranslateProvider.kt

class TranslateProvider {

    @Inject
    constructor() {
        App.appComponent.inject(this)
    }

    @Inject
    lateinit var retrofitProvider: RetrofitProvider
}

But i received a error at TranslateProvider.kt:

kotlin.UninitializedPropertyAccessException: lateinit property appComponent has not been initialized

I'm not understand, please help me.

Thanks!


Solution

  • I created a instance of TranslateProvider in: .translateModule(TranslateModule(TranslateProvider()))

    When constructor of TranslateProvider called appComponent, but appComponent was not initialized that time. Just move it go to out of TranslateModule constructor look like:

    Before:

    @Module
    class TranslateModule(private val translateProvider: TranslateProvider) {
    
        @Provides
        fun getTranslateProvider(): TranslateProvider {
            return translateProvider
        }
    
    }
    

    After:

    @Module
    class TranslateModule {
    
        @Provides
        fun getTranslateProvider(): TranslateProvider {
            return TranslateProvider()
        }
    
    }