【问题标题】:How to properly implement onRestoreInstanceState() for a DialogPreference subclass?如何为 DialogPreference 子类正确实现 onRestoreInstanceState()?
【发布时间】:2013-01-06 11:56:48
【问题描述】:

我正在实现我自己的自定义 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 Preference 类(EditTextPreferenceListPreference)的源代码,onRestoreInstanceState() 中的 UI 小部件没有更新。只有 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 小部件(如果我应该更新它的话......)?

【问题讨论】:

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


    【解决方案1】:

    好的,经过一些实验,看起来更新 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));
    }
    

    【讨论】:

    • 您在自定义DialogPreference 中定义了setValuesetMaxValue 方法吗?如果是这样,您可以发布这些方法的代码吗?
    • 嗯,谢谢。我的问题是我的DialogPreference.getValue() 从对话框内的一些Views 中检索值,当onSaveInstanceStateonRestoreInstanceState 被调用时,这些视图仍然是null 指针。
    猜你喜欢
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多