8

我正在實現自己的自定義DialogPreference子類,該子類具有用於保持整數的SeekBar。我有點困惑,需要進入onSaveInstanceState()onRestoreInstanceState()。具體而言,您是否需要更新onRestoreInstanceState()中與用戶交互的UI小部件(在我的示例中爲SeekBar小部件)?如何正確實現DialogPreference子類的onRestoreInstanceState()?

我感到困惑的原因是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()。只有偏好的基礎值是(在上面的例子中,那將是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

好的,經過一番實驗,看起來像更新onRestoreInstanceState()裏面的UI小部件是不行的,因爲在那一點上它似乎總是null。我不知道他們爲什麼這麼說。也許你必須這樣做,如果子類化首選項,但在繼承DialogPreference子類時有不同的規則...?這至少可以解釋爲什麼ListPreference和EditTextPreference不會這樣做,因爲它們繼承了DialogPreference。

事實上,從我發現的情況來看,UI小部件根本不需要更新!它應該有自己的保存/恢復方法來處理你的狀態管理。例如,這裏是一個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將自行保存/恢復其狀態!

您還會注意到與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)); 
} 
+0

您在自定義的'DialogPreference'中定義了'setValue'和'setMaxValue'方法嗎?如果是這樣,你可以發佈這些方法的代碼? – whatyouhide

+0

@whatyouhide是的。看到我更新的答案。 –

+0

嗯,謝謝。我的問題是,我的'DialogPreference.getValue()'從對話框內的一些'View'中檢索值,當'onSaveInstanceState'和'onRestoreInstanceState'被調用時,這些視圖仍然是'null'指針。 – whatyouhide

相關問題