Algar
Algar

Reputation: 5984

ViewModel in fragment clears values on screen rotation

Guess I'm missing something obvious here but... I'm storing data in uiModel in the DiaryViewModel class, and since I use architecture components I'm expecting the data to be retained through screen rotation - but it doesn't. I'm blind to why.

Here's a stripped down fragment

class DiaryFragment: Fragment() {
    private lateinit var viewModel: DiaryViewModel

    override onCreateView(...) {
        viewModel = ViewModelProviders.of(this).get(DiaryViewModel::class.java)
        viewModel.getModel().observe(this, Observer<DiaryUIModel> { uiModel ->
            render(uiModel)
        })
    }
}

And the corresponding view model.

class DiaryViewModel: ViewModel() {
    private var uiModel: MutableLiveData<DiaryUIModel>? = null

    fun getModel(): LiveData<DiaryUIModel> {
        if (uiModel == null) {
            uiModel = MutableLiveData<DiaryUIModel>()
            uiModel?.value = DiaryUIModel()
        }

        return uiModel as MutableLiveData<DiaryUIModel>
    }
}

Can any one see what's missing in this simple example? Right now, uiModel is set to null when rotating the screen.

Upvotes: 12

Views: 6547

Answers (1)

Algar
Algar

Reputation: 5984

The issue was with how the activity was handling the fragment creation. MainActivity was always creating a new fragment per rotation, as in

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    supportFragmentManager
        .beginTransaction()
        .replace(overlay.id, DiaryFragment.newInstance())
        .commit()
}

But of course, it works much better when checking if we have a saved instance, as in

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    if (savedInstanceState == null) {
        supportFragmentManager
            .beginTransaction()
            .replace(overlay.id, DiaryFragment.newInstance())
            .commit()
    }
}

Upvotes: 27

Related Questions