![](/img/trans.png)
[英]Android DialogPreference NullPointerException in onRestoreInstanceState
[英]How to properly implement onRestoreInstanceState() for a DialogPreference subclass?
我正在實現自己的自定義DialogPreference子類,該子類具有用於保留整數的SeekBar。 我對onSaveInstanceState()
和onRestoreInstanceState()
需要輸入的內容有些困惑。 具體來說,您是否需要在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類( EditTextPreference和ListPreference )的源代碼后,不會在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小部件(如果我應該全部更新...)?
好的,經過一些試驗,似乎沒有辦法更新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想知道setValue
和setMaxValue
方法在我的DialogPreference子類中是什么樣。 他們來了:
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.