October 14, 2013

Parcelable vs. Java Serialization in Android App Development

Android developers often face a predicament while passing object references to activities of whether to go with the Java Serialization method or opt for Android Parcelable. This blog is my attempt to compare the two techniques and cite an example to help decide which one of these is the best approach for passing an object from one activity to another.

Passing primitive data types like string, integer, float, etc. through intents is quite easy in Android. All you have to do is put the data with unique key in intents and send it to another activity. If a user wants to send Java objects through intent, Java class should be implemented using the Parcelable interface. Serialization, on the other hand, is a Java interface that allows users to implement the interface which gets marked as Serializable.

During the Android application development process, developers often have to send Java class objects from one activity to another activity using the intent. Developers can opt from the two types of object passing techniques, i.e. Serialization and Parcelable of object.  The fact that Parcelable is faster than Serialization makes it a preferred choice of approach while passing an object. Here’s why:

Implementation

Android Parcelable implementation allows objects to read and write from Parcels which can contain flattened data inside message containers.

If a developer wants to convert a Java object into Parcelable, then the best way to do so is by implementing the Parcelable interface and overriding the writeToParcel() methods in its own class. The first step is to override the writeToParcel() method and  write all object members into parcel objects. The second is to create a static Parcelable.Creator object to de-serialize the Java object.

Differences between Serialization and Parcelable

Parcelable and Serialization are used for marshaling and unmarshaling Java objects.  Differences between the two are often cited around implementation techniques and performance results. From my experience, I have come to identify the following differences in both the approaches:

·         Parcelable is well documented in the Android SDK; serialization on the other hand is available in Java. It is for this very reason that Android developers prefer Parcelable over the Serialization technique.

·         In Parcelable, developers write custom code for marshaling and unmarshaling so it creates less garbage objects in comparison to Serialization. The performance of Parcelable over Serialization dramatically improves (around two times faster), because of this custom implementation.

·         Serialization is a marker interface, which implies the user cannot marshal the data according to their requirements. In Serialization, a marshaling operation is performed on a Java Virtual Machine (JVM) using the Java reflection API. This helps identify the Java objects member and behavior, but also ends up creating a lot of garbage objects. Due to this, the Serialization process is slow in comparison to Parcelable.

I ran a test and here are my findings:

Intent intent = new Intent(ParcelableActivity.this, RegistrationSuccessActivity.class);
intent.putExtra("data",regiterPogo);
/// for Parcelable list
intent.putParcelableArrayListExtra("data", pacableArray);
/// retrieve in another activity
RegistrationPogo registrationPogo= getIntent().getParcelableExtra("data");
RegistrationPogo.Java
package com.threepillar.bestpractice.ui;
import Java.util.HashMap;
import Java.util.LinkedHashMap;
import Java.util.Map;
import Android.os.Parcel;
import Android.os.Parcelable;
import Android.widget.EditText;
public class RegistrationPogo implements Parcelable {
	String firstName = "", lastName = "", emailAddress = "", phoneNumber = "",
			city = "", state = "";
	int zipCode;
	HashMap<string, String> mapRegData = new HashMap<string, String>();
	public HashMap<string, String> getMapRegData() {
		return mapRegData;
	}
	public void setMapRegData(HashMap<string, String> mapRegData) {
		this.mapRegData = mapRegData;
	}
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmailAddress() {
		return emailAddress;
	}
	public void setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
	}
	public String getPhoneNumber() {
		return phoneNumber;
	}
	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
	public int getZipCode() {
		return zipCode;
	}
	public void setZipCode(int zipCode) {
		this.zipCode = zipCode;
	}
	@Override
	public int describeContents() {
		// TODO Auto-generated method stub
		return 0;
	}
	public RegistrationPogo() {
	}
	@Override
	public void writeToParcel(Parcel dest, int flags) {
		// TODO Auto-generated method stub
		dest.writeString(firstName);
		dest.writeString(lastName);
		dest.writeString(emailAddress);
		dest.writeString(phoneNumber);
		dest.writeString(state);
		dest.writeString(city);
		dest.writeInt(zipCode);
		final int N = mapRegData.size();
		// dest.writeInt(N);
		if (N > 0) {
			for (Map.Entry<string, String> entry : mapRegData.entrySet()) {
				dest.writeString(entry.getKey());
				String dat = entry.getValue();
				dest.writeString(dat);
			}
		}
	}
	public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
		public RegistrationPogo createFromParcel(Parcel in) {
			return new RegistrationPogo(in);
		}
		public RegistrationPogo[] newArray(int size) {
			return new RegistrationPogo[size];
		}
	};
	private RegistrationPogo(Parcel in) {
		firstName = in.readString();
		lastName = in.readString();
		emailAddress = in.readString();
		phoneNumber = in.readString();
		city = in.readString();
		state = in.readString();
		zipCode = in.readInt();
		final int N = in.readInt();
		for (int i = 0; i < N; i++) {
			String key = in.readString();
			String value = in.readString();
			mapRegData.put(key, value);
		}
	}
}

Speed Testing Results

In this example, Android Parcelable came out to be faster than the Java Serialization technique. One of the main reasons was the fact that Parcelable is fully customizable, allowing developers to convert required data into Parcelable. Serialization is a marker interface as it converts an object into a stream using the Java reflection API. Due to this it ends up creating a number of garbage objects during the stream conversation process. So my final verdict will be in favor of Android Parcelable over the Serialization approach. I have tested both performances on HTC Desire, Nexus 4 and Samsung Galaxy S3 and my findings can be viewed in the graphical representation that follows. The scale on the y-axis is the number of milliseconds it took Parcelable and Serialization to return results based on the API calls above.

Speed Testing Results