Mobile - - By Simon Codrington

Transfer Data between Activities with Android Parcelable

An Android app typically consists of more than one activity that need to pass data between each other. For example a primary activity with a list of elements and a corresponding secondary activity to show the details of these elements. To move from one activity to another you use the intent class to connect them together. This lets you launch an activity and optionally return later (If you’re new to intents there’s a good resource in the Google dev docs that explains the process)

Part of the process is sending data between activities and you do that via the putExtra and getExtra methods of our intent object. The idea is to make the process of passing different types of data easy as:

//Inside first activity
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
intent.putExtra("name", "John Smith");
intent.putExtra("age", 26);

//inside second activity
Intent intent = getIntent();
String suburb = intent.getStringExtra("name");
Integer age = intent.getIntExtra("age");

This works well for basic data types such as string, bool, and Integer but doesn’t work for objects. What should you do when you want to pass an object and its data from one activity to the other? You use the parcelableinterface

Introducing the Parcelable Interface

Since objects can contain any number of mixed data types you can’t use putExtra to move values across. Java has had the ability to serialize objects for a while, but it’s a slow process as the system needs to perform heavy lifting to move the data. Parcelable is an Android only Interface used to serialize a class so its properties can be transferred from one activity to another.

Implementing Parcelable

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.

For this example you’ll look at how to implement parcelable in a simple class. I used this class in one of my previous articles where I created a property listing and a corresponding detail activity. The idea is that when you select a property in the list view you’re taken to an expanded detail view to find out more info.

Example Screens

Creating the Property Class

First create a class to hold info about each property. Start by adding the following into a new class file in your project.

public class Property implements {
    //property basics
    private int streetNumber;
    private String streetName;
    private String suburb;
    private String state;
    private String description;
    private String image;
    private Double price;
    private int bedrooms;
    private int bathrooms;
    private int carspots;
    private Boolean featured;

    //main constructor
    public Property(int streetNumber, String streetName, String suburb, String state, String description, Double price, String image, int bedrooms, int bathrooms, int carspots, Boolean featured){

        this.streetNumber = streetNumber;
        this.streetName = streetName;
        this.suburb = suburb;
        this.state = state;
        this.description = description;
        this.price = price;
        this.image = image;
        this.bedrooms = bedrooms;
        this.bathrooms = bathrooms;
        this.carspots = carspots;
        this.featured = featured;
    }


    //getters
    public int getStreetNumber() { return streetNumber; }
    public String getStreetName() {return streetName; }
    public String getSuburb() {return suburb; }
    public String getState() {return state; }
    public String getDescription() {return description; }
    public Double getPrice() {return price; }
    public String getImage() { return image; }
    public int getBedrooms(){ return bedrooms; }
    public int getBathrooms(){ return bathrooms; }
    public int getCarspots(){ return carspots; }
    public Boolean getFeatured(){return featured; }
}

The class contains a series of properties, getter functions and a constructor to create a single object of the class.

Add the Parcelable Interface

Here’s the main part, implementing the interface. Change the declaration of the class as follows:

public class Property implements Parcelable {
  ...
}

Add the following methods inside the class. I’ll run through how they work shortly.

//write object values to parcel for storage
public void writeToParcel(Parcel dest, int flags){
    //write all properties to the parcle
}

//constructor used for parcel
public Property(Parcel parcel){
    //read and set saved values from parcel
}

//creator - used when un-parceling our parcle (creating the object)
public static final Parcelable.Creator<Property> CREATOR = new Parcelable.Creator<Property>(){

    @Override
    public Property createFromParcel(Parcel parcel) {
        return new Property(parcel);
    }

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

//return hashcode of object
public int describeContents() {
    return hashCode();
}

Parcelable needs this code to function. It handles the process of copying your object data into a parcel for transmission between activities and then re-creating the object on the other side.

Let’s break down how this all works.

Writing Method – writeToParcel

In this method you add all your class properties to the parcel in preparation for transfer. You use each of the write methods to add each of your properties.

//write object values to parcel for storage
public void writeToParcel(Parcel dest, int flags){
    dest.writeString(streetName);
    dest.writeString(suburb);
    dest.writeString(state);
    dest.writeString(description);
    dest.writeString(image);
    dest.writeInt(streetNumber);
    dest.writeValue(featured);
    dest.writeDouble(price);
    dest.writeInt(bedrooms);
    dest.writeInt(bathrooms);
    dest.writeInt(carspots);
}

Notes:

  • The order in which you write these values is important. When collecting these values later you will need to collect them in the same order.
  • If you’re going to send boolean values (for example the featured property). You will have to use writeValue and then force cast it to a boolean on the other side as there is no native method for adding booleans.

Reading Method – Property

This method is the constructor, called on the receiving activity, where you will be collecting values.

When the secondary activity calls the getParcelableExtra method of the intent object to start the process. This constructor is where you collect the values and set up the properties of the object:

//constructor used for parcel
public Property(Parcel parcel){
    streetName = parcel.readString();
    suburb = parcel.readString();
    state = parcel.readString();
    description = parcel.readString();
    image = parcel.readString();
    streetNumber = parcel.readInt();
    featured = (Boolean) parcel.readValue(null);
    price = parcel.readDouble();
    bedrooms = parcel.readInt();
    bathrooms = parcel.readInt();
    carspots = parcel.readInt();
}

At this point you’ve populated the object with data.

If you are using your own object then the name of this function will match the name of your own class e.g person, animal, place, the name has to match the class name.

The Creator Method

Parcelable requires this method to bind everything together. There’s little you need to do here as the createFromParcel method will return your newly populated object.

//used when un-parceling our parcel (creating the object)
public static final Parcelable.Creator<Property> CREATOR = new Parcelable.Creator<Property>(){

    @Override
    public Property createFromParcel(Parcel parcel) {
        return new Property(parcel);
    }

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

Other methods – describeContents

This method doesn’t do much.

//return hashcode of object
public int describeContents() {
    return hashCode();
}

Starting the Intent in the First Activity

Inside the first activity create your intent object and use the putExtra method to add the whole class as an extra. This will only work if you’ve implemented the Parcelable interface correctly (as it’s at this point parcelable starts serializing your object).

Intent intent = new Intent(MainActivity.this, DetailActivity.class);
intent.putExtra("Property", property);
startActivity(intent);

If this works, the new activity will open. You will need to ensure the activity is added to your manifest file.

Collecting Values in the Secondary Activity

Now that you’re in the second activity you need to collect the intent object and extract the property class that’s been converted into a parcel. Once you’ve done this you can call the standard methods to get the data like property name, price and description.

//collect our intent
Intent intent = getIntent();
Property property = intent.getParcelableExtra("Property");

//now collect all property values
String streetName = property.getStreetName();
Integer streetNumber = property.getStreetNumber();
String suburb = property.getSuburb();
String state = property.getState();
String description = property.getDescription();
Double price = property.getPrice();
Integer bedrooms = property.getBedrooms();
Integer bathrooms = property.getBathrooms();
Integer carspots = property.getCarspots();
String image = property.getImage();
Integer imageID = this.getResources().getIdentifier(image, "drawable", this.getPackageName());
String address = streetNumber + " " + streetName + ", " + suburb + ", " + state;

Pass the Parcel

As you have see, there’s work involved in getting parcelable up and running, but once it all works the payoff is worth it.

You can move entire objects from one activity to another, retaining all class methods and abilities. This is great if you have a complex method that transforms your data.

You no longer have to remember the different names which you would normally pass to the intent object as extra data, e.g String streetName = intent.getStringExtra("streetName");. You can get your object and move on.

The process is fast and optimized. Doing it this way is faster than using Java’s serialize functionality as you implicitly tell it how to save and extract your data.

Please let me know if you have any comments or questions.

Sponsors
Login or Create Account to Comment
Login Create Account