How to pass object between Activities with Android Parcelable

Android Parcelable

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.

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. Example of passing primitive data types

// inside first activity
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
intent.putExtra("title", "The Godfather");
intent.putExtra("year", 1972);

// inside second activity
Intent intent = getIntent();
String title = intent.getStringExtra("title");
Integer year = intent.getIntExtra("year"); 

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 is converting data from a fast, efficient, internal representation to something that can be kept in a persistent store or transmitted over a network. Converting data to its serialized form is often called marshaling it. Converting it back to its live, in-memory representation is called deserializing or unmarshaling.

Parcel is a serialization mechanism provided by Android. In order to write an object to a Parcel, that object should implement the interface Parcelable.

In order to define a custom parcelable class, we need to implement the interface Parcelable in the class and it must override the methods describeContents() and writeToParcel(Parcel dest, int flags). It is also necessary to create a public static member variable CREATOR that should implement the interface Parcelable.Creator<T>. Parcelable requires this method to bind everything together.

Differences between Parcelable and Serialization are often cited around implementation techniques and performance results. There are some comparison Parcelable vs Serialization:

  • 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 ten 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.

The simplest way to create a Parcelable is to use a third-party library called Parceler. By annotating your Java classes that you intend to use, the library is able to create much of the boilerplate code needed as discussed in the manual steps below.

Also you can build Parcelable using parcelabler.com. Just paste simple POJO class and click Build.

public class Movie {
    private String title;
    private int year;

    public Movie(String title, int year) {
        this.title = title;
        this.year = year;
    }
}

Create a Parcelable class in the file Movie.java

public class Movie implements Parcelable {
    String title;
    int year;

    @Override
    public int describeContents() {
        return 0;
    }

    // Storing the Movie data to Parcel object
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(title);
        dest.writeInt(year);
    }

    // A constructor that initializes the Movie object
    public Movie(String title, int year) {
        this.title = title;
        this.year = year;
    }

    /**
    * Retrieving Movie data from Parcel object
    * This constructor is invoked by the method createFromParcel(Parcel source) of
    * the object CREATOR
    **/
    private Movie(Parcel in){
        this.title = in.readString();
        this.year = in.readInt();
    }

    public static final Parcelable.Creator<Movie> CREATOR = new Parcelable.Creator<Movie>() {
        @Override
        public Movie createFromParcel(Parcel source) {
            return new Movie(source);
        }

        @Override
        public Movie[] newArray(int size) {
            return new Movie[size];
        }
    };
}

We can now pass the parcelable data between activities within an intent

// somewhere inside an Activity
Movie movie = new Movie("The Godfather", 1972);
Intent i = new Intent(this, DetailActivity.class);
i.putExtra("movie", movie); 
startActivity(i); 

and then access the data in the DetailActivity using:

public class DetailActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Movie movie = (Movie) getIntent().getParcelableExtra("movie");
        if (movie != null) {
            tvTitle.setText("Title: " + movie.title);
            tvYear.setText("Year: " + Integer.toString(movie.year));
        } 
    }
}

Useful links

comments powered by Disqus