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

9
我正在实现自己的自定义DialogPreference子类,其中包含一个SeekBar用于持久化整数。我有点困惑需要在onSaveInstanceState()和onRestoreInstanceState()中添加什么内容。具体来说,在onRestoreInstanceState()中是否需要更新用户交互的UI小部件(在我的情况下是SeekBar小部件)?
我感到困惑的原因是API文档文章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 Preference类(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个回答

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是否是持久的,因为这样如果它是持久的,mValue和mMaxValue属性将无法保存。我还在最后调用super.onRestoreInstanceState(),因为我发现如果早些时候调用它,它永远不起作用。
这些只是我迄今为止的发现。我不确定什么是正确的方法,但我上面的方法似乎可行。
更新:@whatyouhide想知道我的DialogPreference子类中setValue和setMaxValue方法是什么样子的。这里是它们:
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));
}

setValuesetMaxValue方法是您在自定义的DialogPreference中定义的吗?如果是,能否发布这些方法的代码? - whatyouhide
谢谢。我的问题是DialogPreference.getValue()从对话框内的某些View中检索值,而当调用onSaveInstanceStateonRestoreInstanceState时,这些视图仍然是空指针。 - whatyouhide

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接