I am implementing my own custom DialogPreference subclass that has a SeekBar used for persisting an integer. I'm a little confused about what needs to go into onSaveInstanceState()
and onRestoreInstanceState()
. Specifically, do you need to update the UI widget that the user interacts with (in my case, the SeekBar widget) in onRestoreInstanceState()
?
The reason I am confused is that the API doc article here tells you to do this:
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
if (isPersistent()) {
return superState;
}
final SavedState myState = new SavedState(superState);
myState.value = mNewValue; //<------------ saves mNewValue
return myState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state == null || !state.getClass().equals(SavedState.class)) {
super.onRestoreInstanceState(state);
return;
}
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
mNumberPicker.setValue(myState.value); //<------------ updates the UI widget, not mNewValue!
}
But looking at the source for some official Android Preference classes (EditTextPreference and ListPreference), the UI widget is not updated in onRestoreInstanceState()
. Only the underlying value of the Preference is (in the example above, that would be mNewValue
).
Here is the relevant source for EditTextPreference:
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
if (isPersistent()) {
return superState;
}
final SavedState myState = new SavedState(superState);
myState.value = getValue(); //<---- saves mValue
return myState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state == null || !state.getClass().equals(SavedState.class)) {
super.onRestoreInstanceState(state);
return;
}
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
setValue(myState.value); //<---- updates mValue, NOT the UI widget!
}
So, what's the consensus? Where I am supposed to update the UI widget (if I am supposed to update it at all...)?
Okay, after some experimentation, it looks like updating the UI widget inside onRestoreInstanceState()
is not the way to go, because it always seems to be null
at that point. I don't know why they suggest it. Perhaps you have to do it if subclassing Preference, but there are different rules to follow when subclassing DialogPreference...? That would at least explain why ListPreference and EditTextPreference don't do it, because they subclass DialogPreference.
In fact, from what I've found, the UI widget does not need to be updated at all! It should have its own save/restore methods that handle its state management for you. For example, here is an excerpt of a DialogPreference subclass I made with a SeekBar widget in it:
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
final SavedState myState = new SavedState(superState);
myState.maxValue = getMaxValue(); //<---- saves mMaxValue
myState.value = getValue(); //<---- saves mValue
return myState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state == null || !state.getClass().equals(SavedState.class))
{
super.onRestoreInstanceState(state);
return;
}
SavedState myState = (SavedState) state;
setMaxValue(myState.maxValue); //<---- updates mMaxValue
setValue(myState.value); //<---- updates mValue
super.onRestoreInstanceState(myState.getSuperState());
}
As you can see, I never update a SeekBar widget anywhere. The SeekBar will save/restore its state all by itself!
You'll also notice there are some slight deviations from what is suggested in the Android developer docs. I don't check if the DialogPreference is persistent before saving state, because then the mValue
and mMaxValue
properties would not get saved if it is. I also call super.onRestoreInstanceState()
right at the end, as I found that it never works when it is called earlier.
These are just my findings so far. I'm not sure what the right way is, but what I have above seems to work.
UPDATE: @whatyouhide wants to know what the setValue
and setMaxValue
methods look like in my DialogPreference subclass. Here they are:
public void setValue(int value)
{
value = Math.max(Math.min(value, mMaxValue), mMinValue);
if (value != mValue)
{
mValue = value;
persistInt(value);
notifyChanged();
}
}
public void setMaxValue(int maxValue)
{
mMaxValue = maxValue;
setValue(Math.min(mValue, mMaxValue));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With