android - 如何为 DialogPreference 子类正确实现 onRestoreInstanceState()?

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

我正在实现我自己的自定义 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 首选项类(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 小部件(如果我应该更新它...)?

最佳答案

好吧,经过一些实验,似乎更新 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));
}

关于android - 如何为 DialogPreference 子类正确实现 onRestoreInstanceState()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14181831/

相关文章:

c++ - 内存状态c++

ios - subview 中的 @State 和 @Published 属性,SwiftUI

android - 从android http登录到grails 3 spring安全

android - isValidFragment Android API 19

android - 当手机进入休眠模式时关闭 AlarmManager

Android 权限拒绝 : broadcasting Intent

android - Unity Firebase 插件在 Android logcat 中抛出 "DllNotFoundException: App"并卡在此时

java - 解析jsoup中元素内的元素?

java - 框架布局 : How to add other Views on top of GLSurfaceView?

reactjs - 如何通过更改任何状态值重新渲染平面列表?