I wanted to retain a complex java object during screen rotation, so I made the object Parcelable and implemented necessary methods:
Then in Fragment's onSaveInstanceState I saved the Parcelable :
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("myObject", myObject);
}
and got my object in Fragment's onCreate :
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyObject myObject = savedInstanceState.getParcelable("myObject");
}
This worked Perfectly.
Then I made the following test:
When I ran the app I got THE EXACT SAME RESULT! I got an object with all the appropriate values in it.
Why did this work? Does Parcelable create Parcelable objects "automatically"?
Yeah, so this has to do with the way Bundle handles caching and parceling internally. When you call putParcelable()
, it runs the following code:
public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
unparcel();
mMap.put(key, value);
mFdsKnown = false;
}
So basically, data in a Bundle
is not immediately written to a Parcel
-- mMap
is an ArrayMap<String, Object>
and it contains a cache of all the objects in the Bundle
as they're inserted or removed.
At some point, writeToParcel()
will be called on the Bundle
, at which point everything in mMap
gets written into mParcelledData
.
So basically, when you do a config change, the Bundle
still hasn't been written to a Parcel
, so the same instance of the object you passed in is still stored in the Bundle
's mMap
(so your Object also has never had writeToParcel()
invoked -- you can confirm this by asserting that the object before and after config change have the same System.identityHashCode()
).
You can see notes about this in BaseBundle
:
// Invariant - exactly one of mMap / mParcelledData will be null
// (except inside a call to unparcel)
ArrayMap<String, Object> mMap = null;
/*
* If mParcelledData is non-null, then mMap will be null and the
* data are stored as a Parcel containing a Bundle. When the data
* are unparcelled, mParcelledData willbe set to null.
*/
Parcel mParcelledData = null;
So if you were to write your Parcelable
object to the save state bundle, and put your app in the background until the process dies (or I believe you can force that by running adb shell am kill <application_id>
) and then resume, you'll then run into the problem where your data isn't parceled correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With