I'm passing a parcelable object to a fragment by adding into a bundle while creating the fragment. In onc instance modification to this parcelled object reflects modification in original object and in another case it is not. I'm a little baffled by this behaviour. Till now I have assumed retrieving a parcelled objects through a bundle always create new object[no sure whether it's shallow copy or deep copy].
Someone please clarify parcelable behaviour.
Bundle is a container for named values of types standard for android (including Parcelable ), which is used to pass data between activies, fragments and other android app entites.
Parcel able is faster than serializable. Parcel able is going to convert object to byte stream and pass the data between two activities. Writing parcel able code is little bit complex compare to serialization. It doesn't create more temp objects while passing the data between two activities.
The Parcelable interface adds methods to all classes you want to be able to transfer between activities. These methods are how parcelable deconstructs the object in one activity and reconstructs it in another.
Serializable is a standard Java interface. You simply mark a class Serializable by implementing the interface, and Java will automatically serialize it in certain situations. Parcelable is an Android specific interface where you implement the serialization yourself.
I was struggling with a similar issue. At the first glance it seems that we always obtain a new deep copy from the parcelled objects. Moreover, there are even some StackOverflow answers which suggest to use Parcelable
interface to clone objects. All this just increases confusion regarding the subject.
Here is what I've found after a lot of searching and googling:
Parcel
documentation. Here is the important quote:An unusual feature of Parcel is the ability to read and write active objects. For these objects the actual contents of the object is not written, rather a special token referencing the object is written. When reading the object back from the Parcel, you do not get a new instance of the object, but rather a handle that operates on the exact same object that was originally written.
Ok, as you can see, there are some special objects that are not being copyed during unparceling. But this is still a bit confusing. Does it mean we have another strong reference to the original object which prevents its garbage collection? And what are the use-cases for such objects?
To answer the aforementioned questions I decided to look through the Android source code. The methods I was looking for are readStrongBinder
and writeStrongBinder
which according to the docs do not cause a new object creation when the parcels are sent/received. And I think I found the desired answer in the ResultReceiver.java class. Here is the interesting line:
mReceiver = IResultReceiver.Stub.asInterface(in.readStrongBinder());
To understand what is this line actually doing we should go to the official AIDL documentation. Here are the most important parts:
The steps a calling class must take to call a remote interface defined with AIDL:
...
5. In your implementation of onServiceConnected(), you will receive an IBinder instance (called service). Call YourInterfaceName.Stub.asInterface((IBinder)service) to cast the returned parameter to YourInterface type.A few comments on calling an IPC service:
Objects are reference counted across processes.
So let's put all things together:
readStrongBinder
method no new instances are being created. We just objtain a new reference to the original object and this reference can prevent its dealllocation.Parcelable
interface implementation.Hope this info will help you.
If you want to read about a real-world example when the confusion regarding Parcelable
objects can cause serious problems check out my blog post.
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