When we want to pass objects between two components in Android, these objects have to implements Android Parcelable interface.Parcelable Android is a serialization and deserialization mechanism as we are used in Java. This post describes how we can use Parcelable interface to pass objects between two Android Activity.
We talked about some basic concepts of Parcelable in Android, in this post we will analyse some more complex example and we will look how we can parcel a List of objects or parcel a class that contains inner class.
Android Parcel object
We know that if we want that Android OS can “serialize” an object it must implement Parcelable interface. To make an object parcelable we have to implements two methods defined in Parcelable interface:
- describeContents()
- writeToParcel(Parcel dest, int flags)
private String name;
private String surname;
private int idx;
// get and set methods
}
[/java]
private String name;
private String surname;
private int idx;
// get and set method
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(surname);
dest.writeInt(idx);
}
// Creator
public static final Parcelable.Creator CREATOR
= new Parcelable.Creator() {
public ContactInfo createFromParcel(Parcel in) {
return new ContactInfo(in);
}
public ContactInfo[] newArray(int size) {
return new ContactInfo[size];
}
};
// “De-parcel object
public ContactInfo(Parcel in) {
name = in.readString();
surname = in.readString();
idx = in.readInt();
}
}
[/java]
As you can notice we have implemented all the requested method. So the android parcel operation is very simple because in the writeToParcel method we simply write all the class attributes and in the Parcel.Creator we read the parcel data. The creator calls a constructor passing Parcel object and here in the constructor we initialise the class attributes.
So now we are ready to pass this object from a caller activity to a receiver activity: in this case the in the caller activity (MainActivity):
// Contact Info
ContactInfo ci = createContact(“Francesco”, “Surviving with android”, 1);
i.putExtra(“contact”, ci);[/java]
while in the receiver activity we have:
[java]Intent i = getIntent();ContactInfo ci = i.getExtras().getParcelable(“contact”);
tv.setText(ci.toString()); // tv is a TextView instance
[/java]
![]() | ![]() |
Android Parcelable List
i.putParcelableArrayListExtra(“contact”, (ArrayList) cList);[/java]
while in the called activity:
[java]<ContactInfo> ciArr = (List) i.getParcelableArrayListExtra(“contact”); [/java]Android Parcel inner class
To parcel an class that contains an inner class we have to modify slightly the code. For example, let us suppose we have a inner class in our ContactInfo that contains the address:
[java]public class ContactInfo implements Parcelable {private String name;
private String surname;
private int idx;
private Address address;
…
// Inner class
public static class Address {
private String street;
private String city;
private int number;
// get and set methods
}
}
[/java]
Now, the first thing is making the inner class parcel able:
[java] // Inner classpublic static class Address implements Parcelable {
private String street;
private String city;
private int number;
public Address() {}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(street);
dest.writeString(city);
dest.writeInt(number);
}
// Creator
public static final Parcelable.Creator
CREATOR = new Parcelable.Creator() {
public Address createFromParcel(Parcel in) {
return new Address(in);
}
public Address[] newArray(int size) {
return new Address[size];
}
};
// “De-parcel object
private Address(Parcel in) {
street = in.readString();
city = in.readString();
number = in.readInt();
}
}
[/java]
Notice that the inner class is now static otherwise it is not parcelable, second in the outer class:
[java]public class ContactInfo implements Parcelable {private String name;
private String surname;
private int idx;
private Address address;
….
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(surname);
dest.writeInt(idx);
// Add inner class
dest.writeParcelable(address, flags);
}
// “De-parcel object
public ContactInfo(Parcel in) {
name = in.readString();
surname = in.readString();
idx = in.readInt();
address = (Address) in.readParcelable(Address.class.getClassLoader());
}
[/java]
At line 30 to unparcel the inner class we used the class loader
Running the example, we have:
Source code available @github
In this post, you gained a knowledge about android parcelable concept in android and how to use it to pass data.
Great! 🙂
This is not the most efficient way to parcel/unparcel an inner class because it requires writing the class metadata when parceling and playing with the classLoader when unparceling. In some cross-process scenarios the unparceling may also fail. In general I recommend this instead:
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(surname);
dest.writeInt(idx);
// Add inner class
address.writeToParcel(dest, flags);
}
// De-parcel object
private ContactInfo(Parcel in) {
name = in.readString();
surname = in.readString();
idx = in.readInt();
address = Address.CREATOR.createFromParcel(in);
}
It's also recommended to make the Parcel constructor private so that only the CREATOR can use it.
Your post save my time
Thank you very much!