2013-02-15 10 views
14

Si supponga di voler derivare la propria classe View da un'implementazione View esistente, aggiungendo un po 'di valore, mantenendo quindi alcune variabili che rappresentano lo stato della propria vista in modo significativo.Ignora View.onSaveInstanceState() e View.onRestoreInstanceState() utilizzando View.BaseSavedState?

Sarebbe bello se la tua vista salverebbe automaticamente il suo stato proprio come fanno gli altri (se è stato assegnato un ID), quindi vorrai sovrascrivere onRestoreInstanceState() e onSaveInstanceState().

Naturalmente, è necessario chiamare i rispettivi metodi della classe base e è necessario combinare le informazioni di stato con quelle della classe base.

Ovviamente, l'unico modo sicuro per farlo è quello di avvolgere la tua super classe 'Parcelable in un proprio Parcelable in modo che le chiavi non vengano confuse.

Ora c'è View.BaseSavedState e interessa getSuperState() metodo, ma in qualche modo non riescono a capire come questo realmente aggiunge valore al solo memorizzare la classe base Parcelable in un Bundle insieme con i valori dello stato della vista derivata e restituire questo. D'altra parte, forse qualche altro componente del sistema si aspetterà che tutte le informazioni di InstanceState siano di tipo View.AbsSavedState (ad esempio in modo che sia possibile chiamare getSuperState())?

Qualche esperienza che sei disposto a condividere?

risposta

11

Penso che il design abbia bisogno di noi e, come suggerisce il nome, di implementare una sottoclasse di View.BaseSavedState per memorizzare i valori sovrascrivendo l'interfaccia di Parcelable.

TextView.SavedState è un buon esempio

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

Grazie! Non ho mai guardato un codice di esempio in questo caso. Questo ha reso tutto molto più chiaro per me. –

+0

writeToParcel non sembra mai essere chiamato da onSaveInstanceState. Qual è lo scopo? – dylan7

+0

@ dylan7 - Viene chiamato dal framework durante la serializzazione dello stato. –

10

Per completare la risposta di James Chen, here è un esempio completo di come utilizzare questo metodo, sulla base di blog article da Charles Harley.

codice dal link:

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]; 
      } 
     }; 
    } 
} 
Problemi correlati