Атрибут объекта ViewModel не инициализирован? - PullRequest
0 голосов
/ 30 августа 2018

Иногда я получаю ошибку UninitializedPropertyAccessException (из аналитики), но приложение никогда не падало во время моего опыта его использования. Я думаю, что после того, как приложение было сброшено в фоновом режиме, а процесс завершен, это происходит, но я не могу воспроизвести эту ошибку.

В своей деятельности я делаю следующее:

private lateinit var viewModel: MyViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.xxx)
    ... // doing other stuff
    viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
    viewModel.init(
            ...,
            ...,
            ...,))
    setUpObservables()
}

и мой MyViewModel выглядит так:

class MyViewModel : ViewModel() {

var lateinit car: String 

fun init(
        car: String,
        ...: String?,
        ...: Boolean 
) {
    if (isInitialized) {
        return
    }
    this.car = car
    ...

    isInitialized = true
}

Позже я пытаюсь получить доступ к car объекту и получить ошибку, если он не инициализирован. Вопрос - как это может произойти? car Объект инициализируется, когда MyViewModel. Есть идеи, как воспроизвести это? Есть идеи как этого избежать?

1 Ответ

0 голосов
/ 30 августа 2018

Хорошо, я добавил ваш код в ViewModel в один из моих рабочих проектов.

lateinit var car: String

fun init(car: String) {
    this.car = car
}

И называется:

viewModel.init("car")
Log.d("CAR_DEBUG",viewModel.car)

И получил в моей консоли ожидаемый вывод: D / CAR_DEBUG: car . Так что это работает, но ошибки могут появляться в зависимости от вашей реализации.

Кроме того, это неправильный способ сделать это, я бы предложил использовать шаблон наблюдателя MutableLiveData, чтобы убедиться, что любое непредвиденное поведение не произойдет из-за поворота экрана или восстановления активности / фрагмента. Имея это в виду, измените ваш код на это:

var carObservable: MutableLiveData<String> = MutableLiveData()

fun init(car: String) {
    carObservable.value = car
}

А в Деятельности / Фрагмент:

viewModel.carObservable.observe(this, Observer {
    Log.d("CAR_DEBUG",it)
})
// doesnt matter where your viewModel.init this will still work
viewModel.init("car")

Таким образом, даже если вы вызываете функцию init после вызова наблюдения, вы уверены, что получите уведомление только при изменении значения. На самом деле это рекомендуемый способ использования ViewModels (реактивный путь через шаблон наблюдателя). И, делая это, вы убедитесь, что даже если вы поворачиваете экран или воссоздаете Activity / Fragment, переменная вашего автомобиля будет доступна.

...