Class Stacker Class Stacker - 3 months ago 19
Android Question

Overriding View.onSaveInstanceState() and View.onRestoreInstanceState() using View.BaseSavedState?

Assume you want to derive your own View class from an existing View implementation, adding a bit of value, hence maintaining a few variables which represent your View's state in a meaningful way.

It would be nice if your View would save its state automatically just like others do (if an ID is assigned) so you would want to override

onRestoreInstanceState()
and
onSaveInstanceState()
.

Of course, you need to call the respective methods of your base class, and you need to combine your state information with that of your base class.

Obviously, the only safe way to do so is to wrap your super class'
Parcelable
in an own
Parcelable
such that the keys won't get mixed up.

Now there's
View.BaseSavedState
and its interesting
getSuperState()
method but I somehow fail to understand how this really adds value to just storing the base class'
Parcelable
in a
Bundle
along with the derived View's state values and return that. On the other hand, maybe some other system component will expect all InstanceState information to be of type
View.AbsSavedState
(e.g. such that
getSuperState()
can be called)?

Any experiences you're willing to share?

Answer

I think the design needs us, and as the name implies, to implement a subclass of View.BaseSavedState to store values by overriding Parcelable's interface.

TextView.SavedState is a good example

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