8

Ich implementiere meine eigene benutzerdefinierte DialogPreference-Unterklasse mit einer SeekBar, die für die Persistenz einer Ganzzahl verwendet wird. Ich bin ein wenig verwirrt darüber, was in onSaveInstanceState() und onRestoreInstanceState() gehen muss. Müssen Sie das UI-Widget, mit dem der Benutzer interagiert (in meinem Fall das SeekBar-Widget), in onRestoreInstanceState() aktualisieren?Wie kann onRestoreInstanceState() für eine DialogPreference-Unterklasse ordnungsgemäß implementiert werden?

Der Grund, warum ich verwirrt bin, ist, dass der API doc Artikel here Sie, dies zu tun sagt:

für einige offiziellen Android Preference Klassen an der Quelle
@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! 
} 

Aber ein Blick (EditTextPreference und ListPreference), der UI-Widget ist nicht aktualisiert in onRestoreInstanceState(). Nur der zugrunde liegende Wert der Präferenz ist (im obigen Beispiel wäre das mNewValue).

Hier ist die relevante Quelle für 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! 
} 

Also, was ist der Konsens? Wo soll ich das UI Widget aktualisieren (wenn ich es überhaupt aktualisieren soll ...)?

Antwort

4

Okay, nach ein paar Experimenten sieht es so aus, als würde das Aktualisieren des UI-Widgets in onRestoreInstanceState() nicht der richtige Weg sein, weil es an diesem Punkt immer null zu sein scheint. Ich weiß nicht, warum sie es vorschlagen. Vielleicht müssen Sie dies tun, wenn Sie Preference ableiten, aber es gibt verschiedene Regeln, die Sie befolgen müssen, wenn Sie DialogPreference ... erstellen? Das würde zumindest erklären, warum ListPreference und EditTextPreference es nicht tun, weil sie DialogPreference ableiten.

In der Tat, von dem, was ich gefunden habe, muss das UI-Widget überhaupt nicht aktualisiert werden! Es sollte eigene Speicher-/Wiederherstellungsmethoden haben, die die Statusverwaltung für Sie übernehmen. Zum Beispiel, hier ist ein Auszug aus einer DialogPreference Unterklasse I mit einem SeekBar Widget in ihm gemacht:

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

Wie Sie sehen können, habe ich nie irgendwo einen SeekBar Widget aktualisieren. Die SeekBar speichert/stellt ihren Status selbst wieder her!

Sie werden auch feststellen, dass es geringfügige Abweichungen von den Vorschlägen in den Android-Entwicklerhandbüchern gibt. Ich überprüfe nicht, ob die DialogPreference vor dem Speichern des Status persistent ist, weil dann die Eigenschaften mValue und mMaxValue nicht gespeichert werden, wenn dies der Fall ist. Ich rufe auch super.onRestoreInstanceState() direkt am Ende, wie ich festgestellt habe, dass es nie funktioniert, wenn es früher aufgerufen wird.

Das sind nur meine bisherigen Ergebnisse. Ich bin mir nicht sicher, was der richtige Weg ist, aber was ich oben habe, scheint zu funktionieren.

UPDATE: @whatyouhide möchte wissen, wie die setValue und setMaxValue Methoden in meiner DialogPreference-Unterklasse aussehen. Hier sind sie:

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

Sind 'setValue' und' setMaxValue' Methoden, die Sie in Ihrer benutzerdefinierten 'DialogPreference' definiert haben? Wenn ja, könnten Sie den Code für diese Methoden veröffentlichen? – whatyouhide

+0

@whatyouhide Ja. Siehe meine aktualisierte Antwort. –

+0

Mmmm, danke. Mein Problem ist, dass mein 'DialogPreference.getValue()' den Wert von einigen 'View's innerhalb des Dialogs abruft, und diese Views sind immer noch 'null' Zeiger, wenn' onSaveInstanceState' und 'onRestoreInstanceState' aufgerufen werden. – whatyouhide

Verwandte Themen