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:
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/CompoundButton.java
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)
{
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 inonRestoreInstanceState()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
Parcelyou can implementParcelablefor 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 caseUUID[]can be stored inParcelasSerializableor you can convertUUID[]toParcelUuid[]and store this array as parcelable array.And a few words about
SavedStateimplementation. The fields inSavedStatewill not be saved if you don’t add them toParcel. So you have to write the toParcelinSavedState.writeToParcel()method. And also you need to read them back inSavedState(Parcel)constructor.