2013-02-15 11 views
14

Załóżmy, że chcesz wyprowadzić własną klasę widoku z istniejącej implementacji widoku, dodając nieco wartości, a więc zachowując kilka zmiennych, które reprezentują twój stan widoku w znaczący sposób.Zastępowanie View.onSaveInstanceState() i View.onRestoreInstanceState() przy użyciu View.BaseSavedState?

Byłoby miło, gdyby Twój widok zapisywał swój stan automatycznie, tak jak robią to inne osoby (jeśli przypisano identyfikator), więc chcesz zastąpić onRestoreInstanceState() i onSaveInstanceState().

Oczywiście musisz wywołać odpowiednie metody swojej klasy bazowej i musisz połączyć informacje o stanie z klasą podstawową.

Oczywiście jedynym bezpiecznym sposobem na to jest zapakowanie superklasy "Parcelable we własne Parcelable, tak aby klucze się nie pomieszały.

Teraz nie View.BaseSavedState i jego ciekawy getSuperState() metoda, ale ja jakoś nie rozumiem, jak to naprawdę dodaje wartość po prostu przechowywania klasę bazową Parcelable w Bundle wraz z wartości stanu widoku potomnej i powrót tego. Z drugiej strony, być może jakiś inny komponent systemowy będzie oczekiwał, że wszystkie informacje o InstanceState będą typu View.AbsSavedState (np. Takie, że można wywołać getSuperState())?

Jakiekolwiek doświadczenia, którymi chcesz się podzielić?

Odpowiedz

11

Myślę, że projekt wymaga nas i jak sama nazwa wskazuje, do wdrożenia podklasy View.BaseSavedState do przechowywania wartości przez nadpisanie interfejsu Parcelable.

TextView.SavedState jest dobrym przykładem

public static class SavedState extends BaseSavedState { 
    int selStart; 
    int selEnd; 
    CharSequence text; 
    boolean frozenWithFocus; 
    CharSequence error; 

    SavedState(Parcelable superState) { 
     super(superState); 
    } 

    @Override 
    public void writeToParcel(Parcel out, int flags) { 
     super.writeToParcel(out, flags); 
     out.writeInt(selStart); 
     out.writeInt(selEnd); 
     out.writeInt(frozenWithFocus ? 1 : 0); 
     TextUtils.writeToParcel(text, out, flags); 

     if (error == null) { 
      out.writeInt(0); 
     } else { 
      out.writeInt(1); 
      TextUtils.writeToParcel(error, out, flags); 
     } 
    } 

    @Override 
    public String toString() { 
     String str = "TextView.SavedState{" 
       + Integer.toHexString(System.identityHashCode(this)) 
       + " start=" + selStart + " end=" + selEnd; 
     if (text != null) { 
      str += " text=" + text; 
     } 
     return str + "}"; 
    } 

    @SuppressWarnings("hiding") 
    public static final Parcelable.Creator<SavedState> CREATOR 
      = new Parcelable.Creator<SavedState>() { 
     public SavedState createFromParcel(Parcel in) { 
      return new SavedState(in); 
     } 

     public SavedState[] newArray(int size) { 
      return new SavedState[size]; 
     } 
    }; 

    private SavedState(Parcel in) { 
     super(in); 
     selStart = in.readInt(); 
     selEnd = in.readInt(); 
     frozenWithFocus = (in.readInt() != 0); 
     text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 

     if (in.readInt() != 0) { 
      error = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 
     } 
    } 
} 
+0

Dziękujemy! Nigdy nie patrzyłem na przykładowy kod w tym przypadku. Dzięki temu wszystko stało się dla mnie bardziej zrozumiałe. –

+0

writeToParcel nigdy nie wydaje się być wywoływana przez onSaveInstanceState. Jaki jest cel? – dylan7

+0

@ dylan7 - To jest wywoływane przez framework podczas serializacji stanu. –

10

celu uzupełnienia odpowiedź James Chen, here jest pełna przykładów, jak używać tej metody, oparte na blogu article Charlesa Harley.

Kod z linkiem:

public class LockCombinationPicker extends LinearLayout { 
    private NumberPicker numberPicker1; 
    private NumberPicker numberPicker2; 
    private NumberPicker numberPicker3; 

    public LockCombinationPicker(Context context) { 
     this(context, null); 
    } 

    public LockCombinationPicker(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public LockCombinationPicker(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     loadViews(); 
    } 

    private void loadViews() { 
     LayoutInflater.from(getContext()).inflate(R.layout.lock_combination_picker, this, true); 
     numberPicker1 = (NumberPicker) findViewById(R.id.number1); 
     numberPicker1.setMinValue(0); 
     numberPicker1.setMaxValue(10); 
     numberPicker2 = (NumberPicker) findViewById(R.id.number2); 
     numberPicker2.setMinValue(0); 
     numberPicker2.setMaxValue(10); 
     numberPicker3 = (NumberPicker) findViewById(R.id.number3); 
     numberPicker3.setMinValue(0); 
     numberPicker3.setMaxValue(10); 
    } 

    @Override 
    protected Parcelable onSaveInstanceState() { 
     Parcelable superState = super.onSaveInstanceState(); 
     return new SavedState(superState, numberPicker1.getValue(), numberPicker2.getValue(), numberPicker3.getValue()); 
    } 

    @Override 
    protected void onRestoreInstanceState(Parcelable state) { 
     SavedState savedState = (SavedState) state; 
     super.onRestoreInstanceState(savedState.getSuperState()); 
     numberPicker1.setValue(savedState.getNumber1()); 
     numberPicker2.setValue(savedState.getNumber2()); 
     numberPicker3.setValue(savedState.getNumber3()); 
    } 

    @Override 
    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 
     // As we save our own instance state, ensure our children don't save and restore their state as well. 
     super.dispatchFreezeSelfOnly(container); 
    } 

    @Override 
    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 
     /** See comment in {@link #dispatchSaveInstanceState(android.util.SparseArray)} */ 
     super.dispatchThawSelfOnly(container); 
    } 

    /** 
    * Convenience class to save/restore the lock combination picker state. Looks clumsy but once created is easy to maintain and use. 
    */ 
    protected static class SavedState extends BaseSavedState { 
     private final int number1; 
     private final int number2; 
     private final int number3; 

     private SavedState(Parcelable superState, int number1, int number2, int number3) { 
      super(superState); 
      this.number1 = number1; 
      this.number2 = number2; 
      this.number3 = number3; 
     } 

     private SavedState(Parcel in) { 
      super(in); 
      number1 = in.readInt(); 
      number2 = in.readInt(); 
      number3 = in.readInt(); 
     } 

     public int getNumber1() { 
      return number1; 
     } 

     public int getNumber2() { 
      return number2; 
     } 

     public int getNumber3() { 
      return number3; 
     } 

     @Override 
     public void writeToParcel(Parcel destination, int flags) { 
      super.writeToParcel(destination, flags); 
      destination.writeInt(number1); 
      destination.writeInt(number2); 
      destination.writeInt(number3); 
     } 

     public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() { 
      public SavedState createFromParcel(Parcel in) { 
       return new SavedState(in); 
      } 

      public SavedState[] newArray(int size) { 
       return new SavedState[size]; 
      } 
     }; 
    } 
} 
Powiązane problemy