9

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

我感到困惑的原因是这里的 API 文档文章告诉你这样做:

@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 小部件(如果我应该更新它......)?

4

1 回答 1

4

好的,经过一些实验,看起来更新内部的 UI 小部件onRestoreInstanceState()不是要走的路,因为它似乎总是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 是否持久,因为如果是的话,mValueandmMaxValue属性将不会被保存。我最后也直接调用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));
}
于 2013-01-14T11:03:11.477 回答