Saving a Var during a configuration change

809 views Asked by At

On screen rotation, I would like to have the var cardcount saved, so the user is not reset to to the first flash card when they rotate the screen.

I have attempted using the onSaveInstanceState and savedInstanceState.getInt() to keep the keep the value on the rotation, but it does not save the value.

I have seen alternatives to these functions, and I am not sure if I am going down some deep rabbit holes for something simple, or if I am swimming in the wrong ocean entirely.

Should I be looking into ViewModels and persistent storage, taking over manually with configuration changes, or shared preferences? The data is one variable, in one fragment.

class Components : Fragment() {

    //Variables to keep track of which card, as well as which side is showing
    private var cardcount = 0
    private var cardfront = true


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        //This is the function to set the image and text for the front and back of the flashard
        fun select_card() {
            card_front.setImageResource(map.getValue(cardcount).image)
            card_back.text = map.getValue(cardcount).text
        }
}
2

There are 2 answers

0
eeqk On BEST ANSWER

That's what ViewModel is for.

As per android docs:

The ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way. The ViewModel class allows data to survive configuration changes such as screen rotations.

https://developer.android.com/topic/libraries/architecture/viewmodel

5
cactustictacs On

You definitely don't need to use ViewModels if you're not already, and SharedPreferences might be too much just for this - but it depends on exactly what you want.

If you just want to keep a value while the app is "open" (including in the background) then the onSaveInstanceState() method is made for that. Pop a value in the Bundle it provides, and when your fragment needs to restore state it will be passed back in through onCreateView, onViewCreated, onViewStateRestored... just pick it up in whichever lifecycle callback is most convenient, check the Bundle isn't null (see next part!) and grab the value with the same key you used to store it.


If the fragment isn't restoring a previous state though, you won't get a bundle passed in. Your app can get closed by the system at any time (say to free up memory), so when it gets restarted, it's meant to look like it was running the whole time - that's why onSaveInstanceState gets called, and why you get a bundle passed in, it's so you can put everything back the way it was when it went into the background.

But if the user closes the app, say by swiping it away, the next time you open it will be a fresh start - there's no state to persist, so you won't get the bundle. So if you do want to persist state between app runs (say the user's choice of language), you'll need to use something like SharedPreferences to store some data, and load that in your Fragment.


ViewModels don't survive process death (the system killing your app in the background), so they don't persist state like onSavedInstanceState does. They're more for things like configuration changes, where the app is going to stay in the foreground. You still have to be able to handle your state getting lost, and being able to recreate it. There are some other libraries to extend ViewModels to help you handle this but... just use a Bundle for an Int in my opinion, keep it simple

Definitely don't override configuration changes! That's a last resort and your example is like, the basic saved instance Bundle use case