Advanced Parcel data in Android: how to parcel complex data structure like java List and inner class
Android Parcelable
Android Parcelable List
Android Parcelable inner class
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 Android Parcelable interface:- describeContents()
- writeToParcel(Parcel dest, int flags)
Moreover, we have to provide Parcelable.Creator that is used to create an instance of the class from the Parcel data.
So let us suppose we have a simple class that contains a contact info:
public class ContactInfo {
private String name;
private String surname;
private int idx;
// get and set methods
}
So to make this object parcelable we have:
public class ContactInfo implements Parcelable {
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.CreatorCREATOR
= 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();
}
}
As you can notice we have implemented all the requested method. So the 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):
Intent i = new Intent(MainActivity.this, ActivityB.class);
// Contact Info
ContactInfo ci = createContact("Francesco", "Surviving with android", 1);
i.putExtra("contact", ci);
while in the receiver activity we have:
Intent i = getIntent();
ContactInfo ci = i.getExtras().getParcelable("contact");
tv.setText(ci.toString()); // tv is a TextView instance
Android Parcelable List
By now, we used a simple example, now we want to create something more complex. Instead using a simple class, we parcel a list of contact.
Now we have that our class is already parcelable, so it is simple; in the caller activity we have:
List%lt;ContactInfo> cList = createContactList();
i.putParcelableArrayListExtra("contact", (ArrayList) cList);
while in the called activity:
List<ContactInfo> ciArr = (List) i.getParcelableArrayListExtra("contact");
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: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
}
}
Now, the first thing is making the inner class parcel able:
// Inner class
public 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();
}
}
Notice that the inner class is now static otherwise it is not parcelable, second in the outer class:
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());
}
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 knowledege about parcel concept in android and how to use it to pass data.
0 comments:
Post a Comment