简体   繁体   English

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

[英]How to properly implement onRestoreInstanceState() for a DialogPreference subclass?

I am implementing my own custom DialogPreference subclass that has a SeekBar used for persisting an integer. 我正在实现自己的自定义DialogPreference子类,该子类具有用于保留整数的SeekBar。 I'm a little confused about what needs to go into onSaveInstanceState() and onRestoreInstanceState() . 我对onSaveInstanceState()onRestoreInstanceState()需要输入的内容有些困惑。 Specifically, do you need to update the UI widget that the user interacts with (in my case, the SeekBar widget) in onRestoreInstanceState() ? 具体来说,您是否需要在onRestoreInstanceState()更新与用户交互的UI小部件(在我的情况下为SeekBar小部件onRestoreInstanceState()

The reason I am confused is that the API doc article here tells you to do this: 我感到困惑的原因是, 这里的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!
}

But looking at the source for some official Android Preference classes ( EditTextPreference and ListPreference ), the UI widget is not updated in onRestoreInstanceState() . 但是,在查看某些官方Android Preference类( EditTextPreferenceListPreference )的源代码后,不会在onRestoreInstanceState()更新UI小部件。 Only the underlying value of the Preference is (in the example above, that would be mNewValue ). 仅Preference的基础值是(在上面的示例中,这将是mNewValue )。

Here is the relevant source for EditTextPreference: 这是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!
}

So, what's the consensus? 那么,共识是什么? Where I am supposed to update the UI widget (if I am supposed to update it at all...)? 我应该在哪里更新UI小部件(如果我应该全部更新...)?

Okay, after some experimentation, it looks like updating the UI widget inside onRestoreInstanceState() is not the way to go, because it always seems to be null at that point. 好的,经过一些试验,似乎没有办法更新onRestoreInstanceState()的UI小部件,因为在那一刻它总是为null I don't know why they suggest it. 我不知道他们为什么建议。 Perhaps you have to do it if subclassing Preference, but there are different rules to follow when subclassing DialogPreference...? 如果将Preference子类化,也许您必须这样做,但是在将DialogPreference子类化时要遵循不同的规则...? That would at least explain why ListPreference and EditTextPreference don't do it, because they subclass DialogPreference. 这至少可以解释为什么ListPreference和EditTextPreference不这样做,因为它们是DialogPreference的子类。

In fact, from what I've found, the UI widget does not need to be updated at all! 实际上,根据我发现的内容,UI小部件根本不需要更新! It should have its own save/restore methods that handle its state management for you. 它应该具有自己的保存/还原方法,可以为您处理状态管理。 For example, here is an excerpt of a DialogPreference subclass I made with a SeekBar widget in it: 例如,以下是我在其中使用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());
}

As you can see, I never update a SeekBar widget anywhere. 如您所见,我从不更新任何地方的SeekBar小部件。 The SeekBar will save/restore its state all by itself! SeekBar将自行保存/恢复其状态!

You'll also notice there are some slight deviations from what is suggested in the Android developer docs. 您还会注意到与Android开发人员文档中建议的内容略有差异。 I don't check if the DialogPreference is persistent before saving state, because then the mValue and mMaxValue properties would not get saved if it is. 在保存状态之前,我不检查DialogPreference是否是持久性的,因为如果保存了mValuemMaxValue属性,则不会保存它。 I also call super.onRestoreInstanceState() right at the end, as I found that it never works when it is called earlier. 我还直接在最后调用了super.onRestoreInstanceState() ,因为我发现它在更早调用时永远无法工作。

These are just my findings so far. 到目前为止,这些只是我的发现。 I'm not sure what the right way is, but what I have above seems to work. 我不确定正确的方法是什么,但是上面的方法似乎可行。

UPDATE: @whatyouhide wants to know what the setValue and setMaxValue methods look like in my DialogPreference subclass. 更新:@whatyouhide想知道setValuesetMaxValue方法在我的DialogPreference子类中是什么样。 Here they are: 他们来了:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM