How can I make my custom objects Parcelable?

AndroidParcelable

Android Problem Overview


I'm trying to make my objects Parcelable. However, I have custom objects and those objects have ArrayList attributes of other custom objects I have made.

What would be the best way to do this?

Android Solutions


Solution 1 - Android

You can find some examples of this here, here (code is taken here), and here.

You can create a POJO class for this, but you need to add some extra code to make it Parcelable. Have a look at the implementation.

public class Student implements Parcelable{
        private String id;
        private String name;
        private String grade;
     
        // Constructor
        public Student(String id, String name, String grade){
            this.id = id;
            this.name = name;
            this.grade = grade;
       }
       // Getter and setter methods
       .........
       .........
       
       // Parcelling part
       public Student(Parcel in){
           String[] data = new String[3];
    
           in.readStringArray(data);
           // the order needs to be the same as in writeToParcel() method
           this.id = data[0];
           this.name = data[1];
           this.grade = data[2];
       }
    
       @Оverride
       public int describeContents(){
           return 0;
       }
    
       @Override
       public void writeToParcel(Parcel dest, int flags) {
           dest.writeStringArray(new String[] {this.id,
                                               this.name,
                                               this.grade});
       }
       public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
           public Student createFromParcel(Parcel in) {
               return new Student(in); 
           }
    
           public Student[] newArray(int size) {
               return new Student[size];
           }
       };
   }

Once you have created this class, you can easily pass objects of this class through the Intent like this, and recover this object in the target activity.

intent.putExtra("student", new Student("1","Mike","6"));

Here, the student is the key which you would require to unparcel the data from the bundle.

Bundle data = getIntent().getExtras();
Student student = (Student) data.getParcelable("student");

This example shows only String types. But, you can parcel any kind of data you want. Try it out.

EDIT: Another example, suggested by Rukmal Dias.

Solution 2 - Android

Here is a website to create a Parcelable Class from your created class:

http://www.parcelabler.com/

Solution 3 - Android

IntelliJ IDEA and Android Studio have plugins for this:

These plugins generate Android Parcelable boilerplate code based on fields in the class.

Plugin demo

Solution 4 - Android

1. Import Android Parcelable code generator

enter image description here

2. Create a class

public class Sample {
    int id;
    String name;
}

3. Generate > Parcelable from menu

enter image description here enter image description here

Done.

Solution 5 - Android

How? With annotations.

You simply annotate a POJO with a special annotation and library does the rest.

> ### Warning! > I'm not sure that Hrisey, Lombok, and other code generation libraries are compatible with Android's new build system. They may or may not play nicely with hot swapping code (i.e. jRebel, Instant Run).

Pros:

  • Code generation libraries save you from the boilerplate source code.
  • Annotations make your class beautiful.

Cons:

  • It works well for simple classes. Making a complex class parcelable may be tricky.
  • Lombok and AspectJ don't play well together. [details]
  • See my warnings.

Hrisey

> ### Warning! > Hrisey has a known issue with Java 8 and therefore cannot be used for Android development nowadays. > See #1 Cannot find symbol errors (JDK 8).

Hrisey is based on Lombok. Parcelable class using Hrisey:

@hrisey.Parcelable
public final class POJOClass implements android.os.Parcelable {
    /* Fields, accessors, default constructor */
}

Now you don't need to implement any methods of Parcelable interface. Hrisey will generate all required code during preprocessing phase.

Hrisey in Gradle dependencies:

provided "pl.mg6.hrisey:hrisey:${hrisey.version}"

See here for supported types. The ArrayList is among them.

Install a plugin - Hrisey xor Lombok* - for your IDE and start using its amazing features!

enter image description here

  • Don't enable Hrisey and Lombok plugins together or you'll get an error during IDE launch.

Parceler

Parcelable class using Parceler:

@java.org.parceler.Parcel
public class POJOClass {
    /* Fields, accessors, default constructor */
}

To use the generated code, you may reference the generated class directly, or via the Parcels utility class using

public static <T> Parcelable wrap(T input);

To dereference the @Parcel, just call the following method of Parcels class

public static <T> T unwrap(Parcelable input);

Parceler in Gradle dependencies:

compile "org.parceler:parceler-api:${parceler.version}"
provided "org.parceler:parceler:${parceler.version}"

Look in README for supported attribute types.


AutoParcel

AutoParcel is an AutoValue extension that enables Parcelable values generation.

Just add implements Parcelable to your @AutoValue annotated models:

@AutoValue
abstract class POJOClass implements Parcelable {
    /* Note that the class is abstract */
    /* Abstract fields, abstract accessors */
  
    static POJOClass create(/*abstract fields*/) {
        return new AutoValue_POJOClass(/*abstract fields*/);
    }
}

AutoParcel in Gradle build file:

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'

repositories {
    /*...*/
    maven {url "https://clojars.org/repo/"}
}

dependencies {
    apt "frankiesardo:auto-parcel:${autoparcel.version}"
}

PaperParcel

PaperParcel is an annotation processor that automatically generates type-safe Parcelable boilerplate code for Kotlin and Java. PaperParcel supports Kotlin Data Classes, Google's AutoValue via an AutoValue Extension, or just regular Java bean objects.

Usage example from docs.
Annotate your data class with @PaperParcel, implement PaperParcelable, and add a JVM static instance of PaperParcelable.Creator e.g.:

@PaperParcel
public final class Example extends PaperParcelable {
	public static final PaperParcelable.Creator<Example> CREATOR = new PaperParcelable.Creator<>(Example.class);

	private final int test;

	public Example(int test) {
		this.test = test;
	}

	public int getTest() {
		return test;
	}
}

For Kotlin users, see Kotlin Usage; For AutoValue users, see AutoValue Usage.


ParcelableGenerator

ParcelableGenerator (README is written in Chinese and I don't understand it. Contributions to this answer from english-chinese speaking developers are welcome)

Usage example from README.

import com.baoyz.pg.Parcelable;

@Parcelable
public class User {

	private String name;
	private int age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

The android-apt plugin assists in working with annotation processors in combination with Android Studio.

Solution 6 - Android

Create Parcelable class without plugin in Android Studio

implements Parcelable in your class and then put cursor on "implements Parcelable" and hit Alt+Enter and select Add Parcelable implementation (see image). that's it.

enter image description here

Solution 7 - Android

I have found simplest way to create Parcelable class

enter image description here

Solution 8 - Android

It is very easy, you can use a plugin on android studio to make objects Parcelables.

public class Persona implements Parcelable {
String nombre;
int edad;
Date fechaNacimiento;

public Persona(String nombre, int edad, Date fechaNacimiento) {
    this.nombre = nombre;
    this.edad = edad;
    this.fechaNacimiento = fechaNacimiento;
}

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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.nombre);
    dest.writeInt(this.edad);
    dest.writeLong(fechaNacimiento != null ? fechaNacimiento.getTime() : -1);
}

protected Persona(Parcel in) {
    this.nombre = in.readString();
    this.edad = in.readInt();
    long tmpFechaNacimiento = in.readLong();
    this.fechaNacimiento = tmpFechaNacimiento == -1 ? null : new Date(tmpFechaNacimiento);
}

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

    public Persona[] newArray(int size) {
        return new Persona[size];
    }
};}

Solution 9 - Android

Now you can use Parceler library to convert your any custom class in parcelable. Just annotate your POJO class with @Parcel. e.g.

    @Parcel
    public class Example {
    String name;
    int id;

    public Example() {}

    public Example(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getName() { return name; }

    public int getId() { return id; }
}

you can create an object of Example class and wrap through Parcels and send as a bundle through intent. e.g

Bundle bundle = new Bundle();
bundle.putParcelable("example", Parcels.wrap(example));

Now to get Custom Class object just use

Example example = Parcels.unwrap(getIntent().getParcelableExtra("example"));

Solution 10 - Android

Android parcable has some unique things. Those are given bellow:

  1. You have to read Parcel as the same order where you put data on parcel.
  2. Parcel will empty after read from parcel. That is if you have 3 data on your parcel. Then after read 3 times parcel will be empty.

Example: To make a class Parceble it must be implement Parceble. Percable has 2 method:

int describeContents();
void writeToParcel(Parcel var1, int var2);

Suppose you have a Person class and it has 3 field, firstName,lastName and age. After implementing Parceble interface. this interface is given bellow:

import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable{
    private String firstName;
    private String lastName;
    private int age;

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

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

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(firstName);
        parcel.writeString(lastName);
        parcel.writeInt(age);
    }

}

Here writeToParcel method we are writing/adding data on Parcel in an order. After this we have to add bellow code for reading data from parcel:

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

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

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

Here, Person class is taking a parcel and getting data in same an order during writing.

Now during intent getExtra and putExtra code is given bellow:

Put in Extra:

Person person=new Person();
                person.setFirstName("First");
                person.setLastName("Name");
                person.setAge(30);

                Intent intent = new Intent(getApplicationContext(), SECOND_ACTIVITY.class);
                intent.putExtra()
                startActivity(intent); 

Get Extra:

Person person=getIntent().getParcelableExtra("person");

Full Person class is given bellow:

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

public class Person implements Parcelable{
    private String firstName;
    private String lastName;
    private int age;



    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

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

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(firstName);
        parcel.writeString(lastName);
        parcel.writeInt(age);
    }

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

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

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

}

Hope this will help you 
Thanks :)

Solution 11 - Android

To put: bundle.putSerializable("key",(Serializable) object);

To get: List<Object> obj = (List<Object>)((Serializable)bundle.getSerializable("key"));

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJean JimenezView Question on Stackoverflow
Solution 1 - AndroidKiril KirilovView Answer on Stackoverflow
Solution 2 - Androidfrancisco_ssbView Answer on Stackoverflow
Solution 3 - AndroidnaXa stands with UkraineView Answer on Stackoverflow
Solution 4 - AndroidkenjuView Answer on Stackoverflow
Solution 5 - AndroidnaXa stands with UkraineView Answer on Stackoverflow
Solution 6 - AndroidVishal NagvadiyaView Answer on Stackoverflow
Solution 7 - AndroidRjz SatvaraView Answer on Stackoverflow
Solution 8 - AndroidApp-SoftwareFactoryView Answer on Stackoverflow
Solution 9 - AndroidShubham ShuklaView Answer on Stackoverflow
Solution 10 - AndroidMd. Sajedul KarimView Answer on Stackoverflow
Solution 11 - AndroidMacárioView Answer on Stackoverflow