Переопределить View.onSaveInstanceState() и View.onRestoreInstanceState() с помощью View.BaseSavedState? - программирование
Подтвердить что ты не робот

Переопределить View.onSaveInstanceState() и View.onRestoreInstanceState() с помощью View.BaseSavedState?

Предположим, вы хотите получить свой собственный класс View из существующей реализации View, добавив немного значения, и, следовательно, поддерживая несколько переменных, которые представляют ваше состояние View значимым образом.

Было бы неплохо, если бы ваш View автоматически сохранил свое состояние, как это делают другие (если ID назначен), поэтому вы хотите переопределить onRestoreInstanceState() и onSaveInstanceState().

Конечно, вам нужно вызвать соответствующие методы вашего базового класса, и вам нужно совместить информацию о состоянии с базовым классом.

Очевидно, единственный безопасный способ сделать это - обернуть суперкласс 'Parcelable в собственный Parcelable, чтобы ключи не смешивались.

Теперь View.BaseSavedState и его интересный метод getSuperState(), но я почему-то не понимаю, как это действительно добавляет ценность только для хранения базового класса Parcelable в Bundle вместе с полученными значениями состояния View и вернуть их. С другой стороны, может быть, какой-то другой системный компонент будет ожидать, что вся информация экземпляра InstanceState будет иметь тип View.AbsSavedState (например, такой, что getSuperState() можно вызвать)?

Любой опыт, который вы готовы поделиться?

4b9b3361

Ответ 1

Я думаю, что дизайн нуждается в нас, и, как следует из названия, для реализации подкласса View.BaseSavedState для хранения значений путем переопределения интерфейса Parcelable.

TextView.SavedState - хороший пример

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

Ответ 2

Чтобы дополнить ответ Джеймса Чена, здесь - это полный пример того, как использовать этот метод на основе блога статья Чарльза Харли.

Код по ссылке:

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