2016-07-30 2 views
0

Я пытаюсь сохранить экземпляр приложения и использовать в конструкторе databaseHelper, но когда моя деятельность пытается создать экземпляр databaseHelper я получаю следующие исключения:App сбой, потому что lateinit экземпляр приложения не инициализирован

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 

в код ведущего к исключению является следующее:

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

ForecastProvider имеет следующий сопутствующий объект:

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

конструктор ForecastDb ссылается на экземпляр ForecastDbHelper, чей конструктор относится к App.instance, объявленный следующим образом:

class App : Application() { 

    companion object { 
    lateinit var instance: App 
    } 

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

} 

Если я комментирую весь код со ссылкой на базу данных, приложение работает с использованием ForecastServer в качестве источника данных, но в тот момент, когда я пытаюсь обратиться к базе данных и, следовательно, к App istance, Kotlin выбрасывает UninitializedPropertyAccessException.

Я смотрел код в течение нескольких часов, не могу понять, что я делаю неправильно. Любая помощь благословляется, благодарю всех вас заранее.

+0

Вы подтвердили, что OnCreate приложения будет реально работать? Возможно, забыли добавить его в манифест. – FWeigl

+0

Спасибо большое! Я не могу поверить, что потерял три часа на этом и не заметил, что моя точка останова в App.onCreate ничего не делает. Можете ли вы написать это как ответ, чтобы я мог принять его? :) –

ответ

1

Не могу точно определить, почему ваш подход не работает, но я могу предложить a fix:

Вам нужен ForecastDb в вашем MainActivity. Вашему ForecastDb нужен ForecastDbHelper. Вашему ForecastDbHelper нужен экземпляр Application.

Так что в вашем MainActivity вы делаете:

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

и вуаля, вы получили ваш дб готов.

Это называется инъекцией зависимостей и дает вам больше контроля над созданием объектов, которые сами выбирают свои зависимости.

EDIT: Кроме того, проверьте, если вы добавили App класс как Application в AndroidManifest.xml как это ::

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

Я не эксперт Kotlin, но кажется, что объекты-компаньоны инициализируются ранее, которые вызывают конструктор родительского класса. Вероятно, когда ваш val SOURCES попытается инициализировать, он выдает исключение, поскольку он пытается использовать унифицированный экземпляр приложения (до приложения onCreate()). Here вы можете прочитать, что объект компаньона инициализируются, когда соответствующий класс загружается (разрешено), соответствие семантики статического инициализатора Java

+0

Хорошо, я только что тестировал, и мои приложения onCreate запускаются до загрузки других классов, и я думаю, что это поведение гарантировано. – FWeigl

+0

Спасибо за ваш ответ и, указав это, я не обратил на это внимания, но я думаю, что вам нужна аннотация @JvmStatic, чтобы позволить им вести себя как таковые. –

Смежные вопросы