Question

Pass Objects Between Activities in Android Java with Parcelable

javaandroidobjectandroid-intentandroid-activity

Question

How can I send an instance of my Customer class from one Android Activity to another and display its values in the destination Activity?

My current class stores a customer's first name, last name, age, and address:

public class Customer {
    private String firstName;
    private String lastName;
    private String address;
    private int age;

    public Customer(String fname, String lname, int age, String address) {
        firstName = fname;
        lastName = lname;
        this.age = age;
        this.address = address;
    }

    public String printValues() {
        return "First Name: " + firstName
                + " Last Name: " + lastName
                + " Age: " + age
                + " Address: " + address;
    }
}

What is the correct way to pass this object through an Intent and read it in the second Activity?

Short Answer

Android activities should exchange small pieces of data through an Intent and its extras. By the end of this page, you will know how to make a Java object Parcelable, attach it to an Intent, retrieve it safely in another activity, and display its contents.

Concept

An Android Activity is a screen with its own lifecycle. When one activity starts another, Android does not give the second activity direct access to the first activity's variables or object references.

Instead, the first activity places transferable data into an Intent. The receiving activity reads that data from the intent's extras.

For a custom class such as Customer, Android needs instructions for converting the object into a form it can transfer and later rebuild. The preferred Android mechanism is Parcelable.

Parcelable matters because Android may need to pass data between components, save temporary UI state, or recreate activities after a configuration change or process recreation. A parcelable object provides the information Android needs to serialize and reconstruct the data.

Use this approach for small data-transfer objects. Do not send large images, large lists, database records, or sensitive data through intent extras. For larger data, pass an ID and load the full data in the destination activity.

Mental Model

Think of an Intent as a delivery envelope sent from one screen to another.

  • The destination activity is the address on the envelope.
  • Extras are the items placed inside it.
  • A Customer object cannot be placed inside without packing instructions.
  • Implementing Parcelable gives Android a packing list: how to write each field into the parcel and how to rebuild the object later.

The second activity opens the envelope, takes out the Customer, and uses its data.

Take Quiz

Syntax and Examples

A custom object can be passed in an intent when it implements Parcelable.

// Sending activity
Intent intent = new Intent(CurrentActivity.this, DetailsActivity.class);
intent.putExtra(DetailsActivity.EXTRA_CUSTOMER, customer);
startActivity(intent);
// Receiving activity
Customer customer = getIntent().getParcelableExtra(DetailsActivity.EXTRA_CUSTOMER, Customer.class);

On older Android API levels, use the older overload:

Customer customer = getIntent().getParcelableExtra(DetailsActivity.EXTRA_CUSTOMER);

A parcelable Customer class

import android.os.Parcel;
import android.os.Parcelable;

public class Customer implements Parcelable {
    private final String firstName;
    private final String lastName;
    private final String address;
    private final int age;

    public Customer(String firstName, String lastName, int age, String address) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.address = address;
    }

    protected Customer(Parcel in) {
        firstName = in.readString();
        lastName = in.readString();
        age = in.readInt();
        address = in.readString();
    }

    public String printValues() {
        return "First Name: " + firstName
                + "\nLast Name: " + lastName
                + "\nAge: " + age
                + "\nAddress: " + address;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(firstName);
        dest.writeString(lastName);
        dest.writeInt(age);
        dest.writeString(address);
    }

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

    public static final Creator<Customer> CREATOR = new Creator<Customer>() {
        @Override
        public Customer createFromParcel(Parcel in) {
            return new Customer(in);
        }

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

The write order and read order must match exactly. This class writes firstName, lastName, age, and address; its parcel constructor reads those same fields in the same order.

Step by Step Execution

Consider this sending code:

Customer customer = new Customer(
        "Ava",
        "Patel",
        29,
        "12 River Road"
);

Intent intent = new Intent(MainActivity.this, CustomerDetailsActivity.class);
intent.putExtra(CustomerDetailsActivity.EXTRA_CUSTOMER, customer);
startActivity(intent);

Execution flow:

  1. A Customer object is created in MainActivity.
  2. An Intent is created with CustomerDetailsActivity as its destination.
  3. putExtra() adds the object under a stable key, EXTRA_CUSTOMER.
  4. Android calls writeToParcel() when it needs to package the customer data.
  5. startActivity() asks Android to open CustomerDetailsActivity.
  6. The destination activity receives the intent and reads the customer:
Customer customer = getIntent().getParcelableExtra(EXTRA_CUSTOMER, Customer.class);
  1. Android uses Customer.CREATOR and the parcel constructor to rebuild a new Customer instance.
  2. The destination checks for null and displays customer.printValues().

The receiving object contains the same field values, but you should not treat it as the same in-memory object reference from the first activity.

Real World Use Cases

  • Product details: pass a small ProductSummary containing a product ID, name, and selected quantity to a checkout screen.
  • Contact preview: pass a Customer or contact summary from a list screen to a details screen.
  • Edit forms: send an existing profile's current values to an edit activity.
  • Search filters: pass a small filter object containing selected category, sort order, and date range.
  • Navigation context: pass a selected order ID and a display label to an order-details screen.

In production applications, it is often better to pass only a stable identifier such as customerId, then query a repository or database in the destination. That avoids stale, oversized, or incomplete objects.

Take Quiz

Real Codebase Usage

Developers usually centralize extra keys in the destination activity so callers do not duplicate string literals.

public class CustomerDetailsActivity extends AppCompatActivity {
    public static final String EXTRA_CUSTOMER =
            "com.example.app.extra.CUSTOMER";
}

They also use a factory method to make navigation harder to misuse:

public static Intent newIntent(Context context, Customer customer) {
    Intent intent = new Intent(context, CustomerDetailsActivity.class);
    intent.putExtra(EXTRA_CUSTOMER, customer);
    return intent;
}

Then callers write:

startActivity(CustomerDetailsActivity.newIntent(this, customer));

A receiving activity should validate required input with a guard clause:

Customer customer = getIntent().getParcelableExtra(EXTRA_CUSTOMER, Customer.class);
if (customer == null) {
    finish();
    return;
}

For data that can change or is stored remotely, use an ID:

intent.putExtra(EXTRA_CUSTOMER_ID, customerId);

The destination can then load the latest record through a repository, ViewModel, API, or local database.

Common Mistakes

Forgetting to implement Parcelable

This does not compile because a plain Customer is not an allowed custom extra type:

intent.putExtra("customer", customer);

Make Customer implement Parcelable, or use Serializable for a simple legacy alternative.

Assigning constructor parameters to themselves

This code leaves the fields unchanged:

public Customer(String firstName, int age) {
    firstName = firstName;
    age = age;
}

The parameter names hide the fields. Use this:

public Customer(String firstName, int age) {
    this.firstName = firstName;
    this.age = age;
}

Reading fields in a different parcel order

Broken example:

// Written as String, then int
parcel.writeString(firstName);
parcel.writeInt(age);

// Incorrectly read as int, then String
age = parcel.readInt();
firstName = parcel.readString();

Always read values in exactly the order and types used to write them.

Assuming the extra always exists

An activity may be opened from a notification, deep link, test, or another screen. The extra can be missing. Check for null before displaying it.

Passing large objects

Intent extras use Binder transactions with size limits. Passing a large bitmap, long list, or large JSON string can crash with TransactionTooLargeException. Pass an ID, URI, or small summary instead.

Using a generic key

Avoid keys such as "data" or "customer" across a large app. Use a namespaced constant such as "com.example.app.extra.CUSTOMER" to reduce collisions.

Comparisons

ApproachBest useAdvantagesLimitations
ParcelableSmall Android data objectsAndroid-focused and efficientMore boilerplate in Java
SerializableQuick prototypes or existing Java classesVery little setupGenerally slower and less preferred on Android
Pass an IDDatabase or API-backed recordsSmall, current data can be loadedDestination must fetch the record
Shared ViewModelScreens within the same navigation scopeAvoids manual argument handling in some architecturesNot a replacement for durable navigation arguments or process recreation

Parcelable versus Serializable

A Serializable version is short:

public class Customer implements java.io.Serializable {
    // fields and methods
}

It can be added with putExtra(), but Parcelable is the usual recommendation for Android component arguments. Prefer Parcelable for new Android Java code when passing a small object.

Passing an object versus passing individual values

You can pass each field separately:

intent.putExtra("first_name", "Ava");
intent.putExtra("age", 29);

This is acceptable for one or two simple values. As fields grow, a Parcelable data object keeps related data together and reduces mismatched keys.

Take Quiz

Cheat Sheet

// 1. Make the class parcelable
public class Customer implements Parcelable { ... }

// 2. Put it in an Intent
Intent intent = new Intent(this, CustomerDetailsActivity.class);
intent.putExtra(CustomerDetailsActivity.EXTRA_CUSTOMER, customer);
startActivity(intent);

// 3. Get it in the destination (API 33+)
Customer customer = getIntent().getParcelableExtra(
        EXTRA_CUSTOMER,
        Customer.class
);
  • Use Parcelable for small custom objects passed between Android components.
  • writeToParcel() order must equal the parcel constructor read order.
  • Put keys in public static final String constants.
  • Check retrieved extras for null.
  • Use this.field = parameter when names match.
  • Pass an ID or URI rather than large data.
  • For older Android API support, use the deprecated one-argument getParcelableExtra(key) where required by your project configuration.

FAQ

Can I pass any Java object between Android activities?

No. A custom object must implement a supported transfer mechanism such as Parcelable or Serializable before it can be placed in an intent extra.

Should I use Parcelable or Serializable on Android?

For a new Android app passing small custom objects, prefer Parcelable. Serializable is simpler but is generally less efficient.

Is the received object the same object instance?

No. Android converts its values into a transferable form and rebuilds an object in the destination. Changes to it do not automatically update the original activity's object.

Why does getParcelableExtra return null?

The key may be incorrect, the caller may not have added the extra, or the activity may have been started from another entry point. Use the same constant for writing and reading, and handle null.

Can I pass a list of Customer objects?

Yes, for a small list of parcelable objects, use putParcelableArrayListExtra(). For large lists, pass IDs or load the data from storage instead.

Can I pass a Customer object back to the first activity?

Yes. The destination can set a result intent containing a parcelable extra, and the original screen can receive it through the Activity Result API.

Why should I pass a customer ID instead of the whole customer?

An ID keeps navigation data small and lets the destination load the latest customer data, which is safer when records can be edited or refreshed.

Take Quiz

Mini Project

Description

Build a small customer-details flow. The first activity creates a Customer and opens a second activity. The second activity receives the parcelable object and displays its values in a TextView. This mirrors a common list-to-details navigation pattern.

Goal

Pass a Customer object safely from MainActivity to CustomerDetailsActivity and render the customer's details.

Requirements

Create a Customer class that implements Parcelable.

Take Quiz

Keep learning

Related questions

View more