Android manage configuration changes(state) in custom view
This is follow up to: Android local variable get's lost when using camera intent
Proper way to do it is to handle onSaveInstanceState
and onRestoreInstanceState
like shown here:
Here is my code:
static class SavedState extends BaseSavedState
{
private String requestedFileName;
private UUID[] mImages = new UUID[4];
SavedState(Parcelable superState)
{
super(superState);
}
private SavedState(Parcel in)
{
开发者_如何学Go super(in);
}
@Override
public void writeToParcel(Parcel out, int flags)
{
super.writeToParcel(out, flags);
}
//required field that makes Parcelables from a Parcel
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];
}
};
}
@Override
public Parcelable onSaveInstanceState()
{
//begin boilerplate code that allows parent classes to save state
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
//end
ss.requestedFileName = this.requestedFileName;
ss.mImages = this.mImages;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state)
{
//begin boilerplate code so parent classes can restore state
if(!(state instanceof SavedState))
{
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState)state;
super.onRestoreInstanceState(ss.getSuperState());
//end
this.requestedFileName = ss.requestedFileName;
this.mImages = ss.mImages;
RestoreImageState();
}
Now to my question. This code seems to work properly and it handles all state changes without a problem. HOWEVER, if you look at SavedState.writeToParcel and SavedState.SavedState you will notice that I do not store my variables there. Do I have to? Why? Problem is that I understand how to wrteToParcel and my data types match. But reading out of parcel not so clear with complex types. And in my tests it wasn't called.
EDIT:
Does this look correct for save/retreive order?
private SavedState(Parcel in)
{
super(in);
this.mName = in.readString();
this.mIndex = in.readInt();
this.mApplicableDamages = (String[])in.readValue(null);
this.mSelectedDamages = (boolean[])in.readValue(null);
}
@Override
public void writeToParcel(Parcel out, int flags)
{
super.writeToParcel(out, flags);
out.writeString(this.mName);
out.writeInt(this.mIndex);
out.writeArray(this.mApplicableDamages);
out.writeBooleanArray(this.mSelectedDamages);
}
You have to save these variables in onSaveInstanceState()
and restore them in onRestoreInstanceState()
later if they're part of your view's state and you don't want to lose them when a parent activity is recreated.
The variables may be lost because when the configuration change happens the parent activity is destroyed and a new activity object is recreated. This new object is receive the previously saved state. And if you don't add some variables to the state the won't be restored.
As to the writing complex types to and reading the from Parcel
you can implement Parcelable
for some parts of the complex type. Or you can just decompose the complex type to the primitive (parcelable) fields and store this fields one by one. In your case UUID[]
can be stored in Parcel
as Serializable
or you can convert UUID[]
to ParcelUuid[]
and store this array as parcelable array.
And a few words about SavedState
implementation. The fields in SavedState
will not be saved if you don't add them to Parcel
. So you have to write the to Parcel
in SavedState.writeToParcel()
method. And also you need to read them back in SavedState(Parcel)
constructor.
static class SavedState extends BaseSavedState
{
private String requestedFileName;
private UUID[] mImages = new UUID[4];
SavedState(Parcelable superState)
{
super(superState);
}
private SavedState(Parcel in)
{
super(in);
requestedFileName = in.readString();
mImages = (UUID[])in.readSerializable();
}
@Override
public void writeToParcel(Parcel out, int flags)
{
super.writeToParcel(out, flags);
out.writeString(requestedFileName);
out.writeSerializable(mImages);
}
//required field that makes Parcelables from a Parcel
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];
}
};
}
精彩评论