如何正确实现DialogPreference子类的onRestoreInstanceState()?

时间:2013-01-06 11:56:49

标签: android android-widget state android-preferences dialog-preference

我正在实现我自己的自定义DialogPreference子类,它有一个用于持久化整数的SeekBar。关于需要进入onSaveInstanceState()onRestoreInstanceState()的内容,我有点困惑。具体来说,您是否需要在onRestoreInstanceState()更新用户与之交互的UI小部件(在我的情况下,是SeekBar小部件)?

我感到困惑的原因是API doc文章here告诉您这样做:

@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!
}

但是查看某些官方Android偏好类(EditTextPreferenceListPreference)的来源,UI小部件未在onRestoreInstanceState()中更新。只有Preference的基础值(在上面的例子中,那将是mNewValue)。

以下是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!
}

那么,什么是共识?在哪里我应该更新UI小部件(如果我应该更新它...)?

1 个答案:

答案 0 :(得分:4)

好的,经过一些实验,看起来更新onRestoreInstanceState()内的UI小部件似乎不是可行的方法,因为此时它似乎总是null。我不知道为什么他们这样做。也许你必须在子类化Preference时这样做,但是当子类化DialogPreference时有不同的规则......?这至少可以解释为什么ListPreference和EditTextPreference不这样做,因为它们是DialogPreference的子类。

事实上,根据我的发现,UI小部件根本不需要更新!它应该有自己的保存/恢复方法,为您处理状态管理。例如,以下是我使用SeekBar小部件制作的DialogPreference子类的摘录:

@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());
}

如您所见,我从不在任何地方更新SeekBar小部件。 SeekBar将自行保存/恢复其状态!

您还会注意到Android开发人员文档中的建议略有偏差。在保存状态之前,我不检查DialogPreference是否持久,因为如果是,mValuemMaxValue属性将不会被保存。我也在最后调用super.onRestoreInstanceState(),因为我发现它在以前调用它时永远不会起作用。

这些只是我迄今为止的调查结果。我不确定正确的方法是什么,但我上面的内容似乎有用。

更新:@whatyouhide想知道我的DialogPreference子类中的setValuesetMaxValue方法是什么样的。他们在这里:

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