Сбой ViewModel при попытке воссоздать без фабрики

Как воссоздать ViewModel, созданный с параметрами, введенными через Factory, после воссоздания экземпляра активности?

ViewModel имеет такой конструктор:

class MyViewModel(
        val model: MyModel,
        val repository: MyRepository
) : ViewModel()

Я создаю его с помощью factory:

ViewModelProviders
                    .of(this, MyViewModelFactory(
                            model = MyModel()
                            repository = MyRepository()))
                    .get(MyViewModel::class.java)

Я пытался восстановить ViewModel вот так, пока savedInstanceState не равно null (активность воссоздается):

ViewModelProviders
                    .of(this)
                    .get(MyViewModel::class.java)

Это вызывает сбой, потому что no 0 arguments constructor присутствует внутри класса MyViewModel.

Что касается передачи factory каждый раз: Моя проблема заключается в том, что все, что я передаю как MyModel в ViewModel, и это происходит из действия Intent, может измениться позже из-за взаимодействия с пользователем. Это будет означать, что при воссоздании MyModel в намерении устаревает модель, которая уже хранится в ViewModel и была изменена взаимодействием с пользователем.


person Jacek Kwiecień    schedule 25.07.2019    source источник
comment
Обратитесь к этому - stackoverflow.com/questions/54419236/   -  person Vishal Arora    schedule 25.07.2019
comment
Ваша ViewModel будет сохранена (вместе с хранящимися в ней данными) во время воссоздания активности. Вам не нужно воссоздавать его после активного отдыха, система Android сделает это за вас.   -  person Praveen Singh    schedule 29.07.2019


Ответы (3)


Это вызывает сбой, поскольку внутри класса MyViewModel отсутствует конструктор с 0 аргументами.

Он рухнет, так как вы не пройдете ни одной фабрики, чтобы построить ViewModel.

Как воссоздать ViewModel, созданную с параметрами, введенными через Factory, после воссоздания экземпляра активности?

Насколько я знаю, поправьте меня, если я ошибаюсь, вам не нужно вручную воссоздавать ViewModel на savedInstanceState. Вы можете использовать viewModel для хранения данных, которые используются в действии. Таким образом, при воссоздании действия ViewModelProvider не будет создавать новый экземпляр viewModel, но предоставит вам старый экземпляр, а данные, хранящиеся в viewModel, не будут очищается. Так что не нужно беспокоиться о savedInstanceState.

СОВЕТ. Если вы хотите управлять созданием фабрики и улучшить процесс воссоздания. вы можете проверить эта статья о ViewModel с Dagger

person theapache64    schedule 25.07.2019
comment
Я думаю, что model и repository могут зависеть от значения savedInstanceState, но не от модели представления. - person Arka Prava Basu; 25.07.2019
comment
Я считаю, что model и repository не должны быть видны Activity и должны быть доступны через viewModel. Почему мы должны использовать savedInstanceState ? @АркаПраваБасу - person theapache64; 25.07.2019
comment
Я считаю, что принципы DI говорят об обратном. Если ViewModel зависит от репозитория и модели, они должны быть внедрены в него вместо того, чтобы ViewModel брал на себя ответственность за их создание. Использование флага savedInstanceState зависит от реализации и варианта использования. На самом деле не зная, какие данные Model хранятся и какие данные нужны Repository, я не уверен, как бы я их использовал. - person Arka Prava Basu; 25.07.2019

В MyViewModel нет конструкторов с 0 аргументами. Когда вы пытаетесь получить экземпляр ViewModel без предоставления Factory, он будет искать конструктор с 0 аргументами.

Вы можете использовать это независимо от того, является ли savedInstanceState null или нет.

ViewModelProviders
                    .of(this, MyViewModelFactory(
                            model,repository))
                    .get(MyViewModel::class.java)

То, как вы создаете repository и model, изменяется на основе значения savedInstanceState, в зависимости от вашего варианта использования или реализации.

person Arka Prava Basu    schedule 25.07.2019

Вероятно, единственный ответ заключается в том, что это невозможно сделать таким образом. Если фабрика была предоставлена, она должна быть предоставлена ​​всегда. Я не знаю механизма ViewModel отдыха, но он не такой умный, как я надеялся.

Моя текущая реализация выглядит так:

    viewModel = ViewModelProviders
            .of(this, MyFactory(MyRepository()))
            .get(MyMViewModel::class.java)

    val binding = DataBindingUtil.setContentView<ActivityCreateFoodstuffBinding>(this, R.layout.my_activity)
    binding.viewModel = viewModel

    if (savedInstanceState == null) {
        val model = intent.getParcelableExtra<MyModel>("model")
        viewModel.model.set(model)
    }

Я использую один конструктор параметров в ViewModel, который всегда использует репозиторий, но модель, которую я удалил, и устанавливаю ее только тогда, когда активность только что создана.

person Jacek Kwiecień    schedule 26.07.2019