2013-09-25 5 views
2

Я пытаюсь справиться с onSaveInstanceState method in class View (не the one in class Activity). Этот метод возвращает Parcelable. Я получил свой собственный View от ViewGroup и перепробовал этот метод для сохранения своего собственного состояния. Но когда государство должно было быть сохранено я получил исключение:Overriding onSaveInstanceState

java.lang.IllegalStateException: 
Derived class did not call super.onSaveInstanceState() 

Это достаточно верно, но просто вызвать этот метод не кажется достаточно для меня. Итак, как мне это сделать? Если метод будет передан Parcel для записи, я мог бы просто передать ту же самую партию суперклассу, так что все будет записываться последовательно. Но это возвращаемое значение.

Должен ли я включать этот возвращенный объект в качестве члена моего собственного представления Parcelable и использовать Parcel.writeParcelable для его маршала вместе с моими собственными данными, если это необходимо? Или есть какой-то лучший способ справиться с вызовом родительских элементов и цепочкой объектов? Если да, то какой загрузчик классов я должен использовать при загрузке состояния экземпляра суперкласса?

+0

Пример, который я недавно обнаружил: https://speakerdeck.com/cyrilmottier/crafting-custom-android-views?slide = 38 – zapl

+0

@zapl: Не вижу, что применительно к моему делу: я не думаю, что я знаю класс BaseSavedState, подходящий для этой цели здесь. Это кажется приятным, если вы контролируете всю иерархию взглядов, но я этого не делаю. Я могу больше согласиться с [слайдом 40] (https://speakerdeck.com/cyrilmottier/crafting-custom-android-views?slide=40): это похоже на мой подход, причем 'superState' как член, который я предложил. – MvG

+0

Эти слайды принадлежат вместе, на слайде 40 вы возвращаете экземпляр своего собственного Parcellable с первого слайда – zapl

ответ

4

Поскольку zapl не включил свой комментарий в ответ, я делаю это.

Есть ли какой-нибудь лучший способ справиться с родительским вызовом и целыми партиями объектов?

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

Типичный пример кода может выглядеть следующим образом:

static class SavedState extends View.BaseSavedState { 
    // include own data members here 
    public SavedState(Parcelable superState) { 
    super(superState); 
    } 
    private SavedState(Parcel in) { 
    super(in); 
    // read own data here 
    } 
    @Override public void writeToParcel(Parcel out, int flags) { 
    super.writeToParcel(out, flags); 
    // write own data here 
    } 
    public static final Parcelable.Creator<SavedState> CREATOR = 
     new Parcelable.Creator<SavedState>() { 
    public SavedState createFromParcel(Parcel in) { return SavedState(in); } 
    public SavedState[] newArray(int size) { return new SavedState[size]; } 
    }; 
} 

@Override public Parcelable onSaveInstanceState() { 
    SavedState state = new SavedState(super.onSaveInstanceState()); 
    // set data members here 
    return state; 
} 

@Override public void onRestoreInstanceState(Parcelable parcelable) { 
    SavedState state = (SavedState)parcelable; 
    super.onRestoreInstanceState(state.getSuperState()); 
    // restore from data members here 
} 

выше была заимствована из this presentation Кирилл Mottier, но также должно быть близкое соответствие с тем, как дизайнеры предназначал использование этого класса в целом.

Должен ли я включить этот возвращенный объект в качестве члена моего Parcelable представления, а также использовать Parcel.writeParcelable маршала его вместе со своими собственными данными, если это необходимо?

Хотя упомянутое вышеописанное представляется предпочтительным, behind the scenes он также полагается на writeParcelable. Поэтому, если есть причины не использовать этот базовый класс, просто вызвать writeParcelable для хранения состояния суперкласса должно быть хорошо.

Какой класс загрузчика следует использовать при загрузке состояния экземпляра суперкласса?

current implementation of AbsSavedState действительно использует null в качестве загрузчика классов аргумента, вызывая использование класса по умолчанию загрузчик. Однако эта строка кода помечена комментарием FIXME, поэтому он может меняться один день.