Search code examples
androidandroid-activitykotlincompanion-object

App crashing because lateinit App instance not initialized


I am trying to save an Application instance and use in the constructor of databaseHelper, but when my activity tries to instantiate the databaseHelper I get the following exceptions:

FATAL EXCEPTION: 
main Process: com.weatherupp.weatherupp, PID: 29092
java.lang.ExceptionInInitializerError
at com.weatherupp.weatherupp.ui.MainActivity.onCreate(MainActivity.kt:27)
[...]
Caused by: kotlin.UninitializedPropertyAccessException: lateinit 
property instance has not been initialized

the code leading to the exception is the following:

MainActivity {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val provider = ForecastProvider()
[...]
}

ForecastProvider has the following companion object:

companion object {
    val SOURCES = listOf(ForecastServer(), ForecastDb())
}

ForecastDb's constructor refers to an instance of ForecastDbHelper, whose constructor refers to App.instance, declared as follows:

class App : Application() {

  companion object {
    lateinit var instance: App
  }

  override fun onCreate() {
    super.onCreate()
    instance = this
  }

}

If I comment all the code referring to the database, the app works using ForecastServer as the source of data, but the moment I try to refer to the database and hence to the App istance, Kotlin throws the UninitializedPropertyAccessException.

I have been looking at the code for hours, can't figure out what I am doing wrong. Any help is blessed, thank all of you in advance.


Solution

  • Cannot exactly pinpoint why your approach isn't working but I can suggest a fix:

    You need a ForecastDb in your MainActivity. Your ForecastDb needs a ForecastDbHelper. Your ForecastDbHelper needs the Application instance.

    So in your MainActivity you do:

    val helper = ForecastDbHelper(application as App)
    val db = ForecastDb(helper)  
    

    and voila, you got your db ready.

    This is called dependency injection and gives you more control over creation of the objects 'fetching' their dependencies themselves.

    EDIT: Also check if you added your App class as the Application in the AndroidManifest.xmllike this::

    <application
        android:name=".base.App" 
        ...