Three Core Methods for Passing Objects Between Activities in Android: A Comparative Analysis

Dec 05, 2025 · Programming · 11 views · 7.8

Keywords: Android | Activity | Object Passing | Parcelable | Serializable | Application | GSON

Abstract: This article provides an in-depth exploration of three primary methods for passing the same object instance between multiple Activities in Android development: using Intent with Parcelable or Serializable interfaces, storing objects globally via the Application class, and JSON serialization using the GSON library. The article analyzes the implementation principles, applicable scenarios, and performance characteristics of each method, offering complete code examples and best practice recommendations.

Core Challenges of Object Passing Between Android Activities

In Android application development, Activities serve as the fundamental units of user interfaces, often requiring data objects to be shared between different Activities. When the same object instance needs to be used across multiple Activities, developers face the core challenge of how to efficiently and securely pass object references while maintaining object integrity and consistency. While the traditional public static variable approach is simple, it carries risks of memory leaks and lifecycle management issues, necessitating more robust solutions.

Method 1: Using Intent with Parcelable or Serializable Interfaces

This is the standard method recommended by Android, passing objects through Intent's Bundle mechanism. Objects need to implement either the Parcelable or Serializable interface, both of which allow objects to be serialized and deserialized for transmission between different components.

Parcelable Interface Implementation: Parcelable is Android's specific serialization mechanism that offers better performance compared to Serializable by avoiding the overhead of Java reflection. Implementing Parcelable requires overriding writeToParcel() and describeContents() methods and creating a Parcelable.Creator static field.

public class CustomObject implements Parcelable {
    private String name;
    private int value;
    
    // Constructor
    public CustomObject(String name, int value) {
        this.name = name;
        this.value = value;
    }
    
    // Parcelable implementation
    protected CustomObject(Parcel in) {
        name = in.readString();
        value = in.readInt();
    }
    
    public static final Creator<CustomObject> CREATOR = new Creator<CustomObject>() {
        @Override
        public CustomObject createFromParcel(Parcel in) {
            return new CustomObject(in);
        }
        
        @Override
        public CustomObject[] newArray(int size) {
            return new CustomObject[size];
        }
    };
    
    @Override
    public int describeContents() {
        return 0;
    }
    
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(value);
    }
    
    // Getter and Setter methods
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getValue() { return value; }
    public void setValue(int value) { this.value = value; }
}

In the sending Activity, objects can be passed as follows:

CustomObject obj = new CustomObject("Example Object", 100);
Intent intent = new Intent(this, TargetActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelable("custom_object", obj);
intent.putExtras(bundle);
startActivity(intent);

In the receiving Activity, objects can be retrieved as follows:

Bundle bundle = getIntent().getExtras();
if (bundle != null) {
    CustomObject obj = bundle.getParcelable("custom_object");
    // Use the obj object
}

Serializable Interface Implementation: Serializable is Java's standard serialization interface, simpler to implement but with poorer performance. Simply have the class implement the Serializable interface:

public class CustomObject implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int value;
    
    // Constructor, Getter and Setter methods
    public CustomObject(String name, int value) {
        this.name = name;
        this.value = value;
    }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getValue() { return value; }
    public void setValue(int value) { this.value = value; }
}

The passing and receiving methods are similar to Parcelable, but use putSerializable() and getSerializable() methods.

Method 2: Global Storage via Application Class

When the same object needs to be frequently accessed across multiple Activities and has a long lifecycle, consider storing it in the Application class. The Application object exists throughout the entire application lifecycle and can serve as a global data container.

First, create a custom Application class:

public class MyApplication extends Application {
    private CustomObject globalObject;
    
    @Override
    public void onCreate() {
        super.onCreate();
        // Initialize global object
        globalObject = new CustomObject("Global Object", 200);
    }
    
    public CustomObject getGlobalObject() {
        return globalObject;
    }
    
    public void setGlobalObject(CustomObject obj) {
        this.globalObject = obj;
    }
}

Register the custom Application in AndroidManifest.xml:

<application
    android:name=".MyApplication"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name">
    <!-- Activity declarations -->
</application>

In any Activity, the global object can be accessed as follows:

MyApplication app = (MyApplication) getApplication();
CustomObject obj = app.getGlobalObject();
// Use the obj object

This method avoids the overhead of object serialization and deserialization but requires attention to memory management and thread safety.

Method 3: JSON Serialization Using GSON Library

For objects with complex nested structures or when objects need to interact with network APIs, using the GSON library for JSON serialization offers a flexible alternative. This method doesn't require modifying the original class structure, passing objects by converting them to JSON strings.

First, add GSON dependency to build.gradle:

dependencies {
    implementation 'com.google.code.gson:gson:2.8.9'
}

In the sending Activity:

CustomObject obj = new CustomObject("JSON Object", 300);
Gson gson = new Gson();
String jsonString = gson.toJson(obj);

Intent intent = new Intent(this, TargetActivity.class);
intent.putExtra("object_json", jsonString);
startActivity(intent);

In the receiving Activity:

String jsonString = getIntent().getStringExtra("object_json");
if (jsonString != null) {
    Gson gson = new Gson();
    CustomObject obj = gson.fromJson(jsonString, CustomObject.class);
    // Use the obj object
}

This method is particularly suitable for scenarios where objects have complex structures, need to interact with REST APIs, or require persistent storage. However, attention should be paid to the performance overhead of JSON serialization, especially for large objects.

Performance Comparison and Best Practices

Each of the three methods has its advantages and disadvantages, making them suitable for different scenarios:

  1. Performance Aspects: Parcelable offers the best performance, suitable for frequently passed small objects; Application storage avoids serialization overhead, suitable for long-lived global objects; GSON serialization offers the highest flexibility but relatively poorer performance.
  2. Implementation Complexity: Serializable is simplest to implement, Parcelable requires manual serialization logic, and GSON requires additional dependencies but no modification to original classes.
  3. Suitable Scenarios:
    • Use Parcelable: When objects need frequent passing between Activities with high performance requirements.
    • Use Application: When objects need sharing across multiple components with lifecycle matching the application.
    • Use GSON: When objects have complex structures or need compatibility with network data formats.

In practical development, event bus frameworks like EventBus or Otto can also be considered, providing looser coupling for inter-component communication. However, these frameworks have steeper learning curves and are more suitable for large, complex applications.

Regardless of the chosen method, several considerations are essential: avoid passing excessively large objects (recommended under 1MB), pay attention to object reference lifecycle management, consider synchronization in multi-threaded environments, and properly handle deep and shallow copying of objects.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.