Search code examples
androidkotlindagger

Android Kotlin with Dagger2, lateinit var has not been initialized


I'm a Dagger newb and have a trouble with using it.

What I want to develop is that using RxAndroidBle and to initialize it by Dagger for providing Context.

So I researched how it can be implemented, and I wrote some codes and It seems to be working for me but not working at all.

The followings are my codes.

AppComponent.kt

@Singleton
@Component(modules = [
    AppModule::class,
    BluetoothModule::class,
    AndroidInjectionModule::class])
interface AppComponent : AndroidInjector<BluetoothController> {

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(app: Application): Builder

        fun build(): AppComponent
    }
}

AppModule.kt

@Module
class AppModule {

    @Provides
    @Named("appContext")
    @Singleton
    fun provideContext(application: Application): Context =
            application.applicationContext
}

BluetoothModule.kt

@Module
class BluetoothModule {

    @Provides
    @Named("rxBleClient")
    @Singleton
    fun provideRxBleClient(@Named("appContext") context: Context):RxBleClient =
            RxBleClient.create(context)
}

BluetoothController.kt for injecting by DaggerApplication.

class BluetoothController : DaggerApplication() {

    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        return DaggerAppComponent.builder().application(this).build()
    }
}

I've inserted android:name".BluetoothController" to AndroidManifest.xml

And this is how I would use it.

@field:[Inject Named("rxBleClient")]
lateinit var rxBleClient: RxBleClient

But it always occurs an error says: lateinit property context has not been initialized

What things I've missed? Can anyone help me?

Thanks in advance.


Solution

  • Add the below code to make this happen.

    1. Create ActivityBuilderModule for injecting within the activity. Consider our activity as MainActivity

      @Module
      abstract class ActivityBuilderModule {
           @ContributesAndroidInjector(modules=[MainActivityModule::class])
           abstract fun contributeSplashActivity(): MainActivity
      }
      
    2. Create your MainActivityModule

      @Module
      class MainActivityModule{
           @Provides()
           fun contributeSplashActivity(mainActivity: MainActivity): 
              MainActivity=mainActivity
       }
      
    3. Modify your component.

      @Singleton
      @Component(modules = [
      AppModule::class,
      BluetoothModule::class,
      ActivityBuilderModule::class,
      AndroidInjectionModule::class])
      interface AppComponent : AndroidInjector<BluetoothController> {
      
          @Component.Builder
          interface Builder {
      
              @BindsInstance
              fun application(app: Application): Builder
      
              fun build(): AppComponent
          }
      }
      
    4. Within MainActivity just inject.

      class MainActivity{
            ...
            @Inject
            lateinit var rxBleClient: RxBleClient
            override fun onCreate(savedInstanceState: Bundle?) {
      
              AndroidInjection.inject(this)
              super.onCreate(savedInstanceState)
            }
      }
      

    Let us know in case of any issue.