I have a class that implements Parcelable
.
I safe this object to the bundle in an activites onSaveInstanceState
and I try to recreate the object in onCreate
. This looks like following:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
// this line does NOT call my constructor, why not?
// AND I don't get the same object as before => I get an uninitialised object
mStackManager = savedInstanceState.getParcelable(BackstackManager.TAG);
// the list and map in the object are NULL after this...
}
else
{
mStackManager = new BackstackManager();
...
}
}
@Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putParcelable(BackstackManager.TAG, mStackManager);
}
When the Parcelable class is created, it should call the cosntructor of the parcelable class, shouldn't it? My parcelable class is retrieved from the bundle, but it does not look like the object that was saved, it even is not initialised...
My simplified parcelable class looks like following:
public class BackstackManager implements Parcelable
{
public static final String TAG = BackstackManager.class.getName();
private List<List<Pair<Class<?>, Pair<Integer, String>>>> mBackstack;
private Map<String, Fragment.SavedState> mSavedStateMap;
public BackstackManager()
{
init();
}
private void init()
{
mBackstack = new ArrayList<List<Pair<Class<?>, Pair<Integer, String>>>>();
mSavedStateMap = new HashMap<String, Fragment.SavedState>();
}
// ----------------------
// Parcelable
// ----------------------
public static final Parcelable.Creator<BackstackManager> CREATOR =
new Parcelable.Creator<BackstackManager>()
{
@Override
public BackstackManager createFromParcel(Parcel source)
{
return new BackstackManager(source);
}
@Override
public BackstackManager[] newArray(int size)
{
return new BackstackManager[size];
}
};
public BackstackManager(Parcel source)
{
init();
readFromParcel(source);
}
@Override
public int describeContents()
{
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeInt(mBackstack.size());
for (int i = 0; i < mBackstack.size(); i++)
{
List<Pair<Class<?>, Pair<Integer, String>>> data = mBackstack.get(i);
dest.writeInt(data.size());
for (int j = 0; j < data.size(); j++)
{
Class<?> clazz = data.get(j).first;
Integer id = data.get(j).second.first;
String tag = data.get(j).second.second;
Fragment f = mFragmentManager.findFragmentByTag(tag);
// 1) save backstack data
ParcelBundleUtils.writeStringNullSafe(dest, clazz != null ? clazz.getName() : null);
dest.writeInt(id);
dest.writeString(tag);
// 2) save fragment state, if possible
ParcelBundleUtils.writeBoolean(dest, f != null);
if (f != null)
ParcelBundleUtils.writeParcelableNullSafe(dest, mFragmentManager.saveFragmentInstanceState(f), 0);
}
}
}
public void readFromParcel(Parcel source)
{
int backstackSize = source.readInt();
for (int i = 0; i < backstackSize; i++)
{
ArrayList<Pair<Class<?>, Pair<Integer, String>>> data = new ArrayList<Pair<Class<?>, Pair<Integer, String>>>();
int dataSize = source.readInt();
for (int j = 0; j < dataSize; j++)
{
// 1) read backstack data
String clazzName = ParcelBundleUtils.readStringNullSafe(source);
Class<?> clazz = null;
if (clazzName != null)
{
try
{
clazz = Class.forName(clazzName);
}
catch (ClassNotFoundException e)
{
L.e(this, e);
}
}
Integer id = source.readInt();
String tag = source.readString();
// 2) read fragment state if possible
boolean savedStateExists = ParcelBundleUtils.readBoolean(source);
if (savedStateExists)
{
SavedState state = ParcelBundleUtils.readParcelableNullSafe(source, SavedState.class.getClassLoader());
if (state != null)
mSavedStateMap.put(tag, state);
}
data.add(new Pair<Class<?>, Pair<Integer, String>>(clazz, new Pair<Integer, String>(id, tag)));
}
mBackstack.add(data);
}
}
}
My ParcelBundleUtils
just write a bit if an object is null or not and dependent on that read/write the actual object...
EDIT
my current workround is to use a read/write function for a bundle that does EXACTLY (I copy and pasted my code and just replaced the read/write functions) the same as the parcel read/write function, but writes the data directly to a bundle... But I really would like to know, why the above is not working as a parcel
EDIT 2
I found following: Android: Parcelable.writeToParcel and Parcelable.Creator.createFromParcel are never called
But if that's the problem, I would not be the only one facing this problem...