Search code examples
androidandroid-architecture-componentsandroid-viewmodelandroid-mvvm

ViewModel crashing while trying to recreate without factory


How to recreate ViewModel that was created with params injected via Factory after instance of activity is recreated?

ViewModel has a constructor like this:

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

I instantiate it with factory:

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

I tried to recover ViewModel like this, while savedInstanceState is not null (activity is recreated):

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

This causes a crash because no 0 arguments constructor is present inside MyViewModel class.

As, for passing factory each time: My problem with that is, that whatever I pass as a MyModel to ViewModel, and that comes from activity Intent, might change later, due to user interaction. That would mean, when recreating, the MyModel in the Intent is outdated to the model that is already stored in ViewModel and was tampered by user interaction.


Solution

  • Probably the only answer is, that it cannot be done this way. If the factory was provided, it has to be provided at all time. I don't know mechanism underneath ViewModel recreation but these are not as smart as I hoped.

    My current implementation looks like this:

        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)
        }
    

    I use one param constructor in ViewModel that always takes repository, but model I moved away and set it only when the activity is freshly created.