How to Make My Custom Objects Parcelable

How can I make my custom objects Parcelable?

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.

Passing custom class objects using parcelable

In your comment you say that CustomClass is made of 4 integer variables. You could therefore do something like this:

class A implements Parcelable {

private CustomClass B;

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(B.getFirst());
dest.writeInt(B.getSecond());
dest.writeInt(B.getThird());
dest.writeInt(B.getFourth());
}

private A(Parcel in) {
B = new CustomClass();
B.setFirst(dest.readInt());
B.setSecond(dest.readInt());
B.setThird(dest.readInt());
B.setFourth(dest.readInt());
}
}

How to write to arraylist of two or more custom objects in Parcelable?

You can add customArray using following way :

In MovieObject class:

  @Expose
private ArrayList< ReviewObject > ReviewObjs = new ArrayList< ReviewObject >();
private ArrayList< TrailerVideoObject > TrailerVideoObjs = new ArrayList< TrailerVideoObject >();

writeToParcel() :

 public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(ReviewObjs);
dest.writeTypedList(TrailerVideoObjs);
}

and readFromParcel() :

private void readFromParcel(Parcel in) {

ReviewObjs = new ArrayList<ReviewObject>();
in.readTypedList(ReviewObjs, ReviewObject.CREATOR);

TrailerVideoObjs = new ArrayList<TrailerVideoObject>();
in.readTypedList(TrailerVideoObjs, TrailerVideoObject.CREATOR);

}

And add following lines in CustomClasses :

for ReviewObject :

public class ReviewObject implements Parcelable {
public static final Creator<ReviewObject> CREATOR = new Creator<ReviewObject>() {
public ReviewObject createFromParcel(Parcel in) {
return new ReviewObject(in);
}

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

};
// add other objects...
}

for TrailerVideoObject :

public class TrailerVideoObject implements Parcelable {
public static final Creator<TrailerVideoObject> CREATOR = new Creator<TrailerVideoObject() {
public TrailerVideoObject createFromParcel(Parcel in) {
return new TrailerVideoObject(in);
}

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

};
// add other objects...
}

Parcelable with custom parcelable object

First solution

@Suppress("UNCHECKED_CAST")
constructor(parcel: Parcel): this(parcel.readString(), parcel.readString(), parcel.readString(), parcel.readArrayList(Tab::class.java.classLoader) as ArrayList<Section>)

Second solution

constructor(parcel: Parcel): this(parcel.readString(), parcel.readString(), parcel.readString(), ArrayList<Section>()){
parcel.readTypedList(sections, Section.CREATOR)
}

Is there a way to make a custom object parcelable when it is constructed using another object?

Solved! There are four main parameters I had to add to this class to get it to be Parcelable.

The first was a protected constructor that took in a Parcel object.

The second was a new static CREATOR object, with internal methods createFromParcel and newArray.

The third was the describeContents function.

Lastly was the writeToParcel function.

Hopefully others are able to learn from this, and sorry if this could be considered a repost!

The modified code can be seen below:

package com.example.marketcheckcarsearchapp;

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

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.Serializable;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;

public class CarListing implements Parcelable
{
/* vehicle parameters */
String make, model, trim, vin, color, condition, transmission, engine, drivetype, seller_type, seller_name, website, city, state;
int year, price, mileage, cylinders;
double distance;
ArrayList<String> images;

/* carfax parameters */
boolean one_owner, clean_title;

/* local variables that may be important */
int index;
JSONObject img_json, build, dealer;
JSONArray img_array;

public HashMap<String, String> listview_hashmap;

/* Most strings are default N/A. Most integers are default 1, or 1970 for the case of years. */
public CarListing(JSONObject input, int index)
{
try
{
this.images = new ArrayList<>();
this.index = index;
this.listview_hashmap = new HashMap<>();

if(input.has("vin")) this.vin = input.getString("vin");
else this.vin = "N/A";

if(input.has("price")) this.price = input.getInt("price");
else this.price = 1;

if(input.has("mileage")) this.mileage = input.getInt("mileage");
else this.mileage = 1;

if(input.has("vdp_url")) this.website = input.getString("vdp_url");
else this.website = "N/A";

if(input.has("carfax_1_owner")) this.one_owner = input.getBoolean("carfax_1_owner");
else this.one_owner = true;

if(input.has("carfax_clean_title")) this.clean_title = input.getBoolean("carfax_clean_title");
else this.clean_title = true;

if(input.has("exterior_color")) this.color = input.getString("exterior_color");
else this.color = "N/A";

if(input.has("seller_type")) this.seller_type = input.getString("seller_type");
else this.seller_type = "N/A";

if(input.has("inventory_type")) this.condition = input.getString("inventory_type");
else this.condition = "N/A";

if(input.has("build"))
{
this.build = input.getJSONObject("build");

if(this.build.has("year")) this.year = this.build.getInt("year");
else this.year = 1970;

if(this.build.has("make")) this.make = this.build.getString("make");
else this.make = "N/A";

if(this.build.has("model")) this.model = this.build.getString("model");
else this.model = "N/A";

if(this.build.has("trim")) this.trim = this.build.getString("trim");
else this.trim = "N/A";

if(this.build.has("transmission")) this.transmission = this.build.getString("transmission");
else this.transmission = "N/A";

if(this.build.has("drivetrain")) this.drivetype = this.build.getString("drivetrain");
else this.drivetype = "N/A";

if(this.build.has("cylinders")) this.cylinders = this.build.getInt("cylinders");
else this.cylinders = 4;

if(this.build.has("engine")) this.engine = this.build.getString("engine");
else this.engine = "N/A";

if(this.build.has("dist")) this.distance = this.build.getDouble("dist");
else this.distance = 0;
}

if(input.has("dealer"))
{
this.dealer = input.getJSONObject("dealer");
if(this.dealer.has("name")) this.seller_name = capitalizeLetters(this.dealer.getString("name"));
else this.seller_name = "N/A";

if(this.dealer.has("city")) this.city = this.dealer.getString("city");
else this.city = "N/A";

if(this.dealer.has("state")) this.state = this.dealer.getString("state");
else this.state = "N/A";
}

if(input.has("media"))
{
this.img_json = input.getJSONObject("media");
if(this.img_json.has("photo_links")) this.img_array = this.img_json.getJSONArray("photo_links");
else this.img_json = null;

int n = this.img_array.length();
for(int i=0;i<n;i++)
{
if(i >= 50) break;
else
{
this.images.add(img_array.getString(i));
}
}
}
}
catch(JSONException ex)
{
System.out.println("JSON Exception thrown");
}
}

protected CarListing(Parcel in) {
make = in.readString();
model = in.readString();
trim = in.readString();
vin = in.readString();
color = in.readString();
condition = in.readString();
transmission = in.readString();
engine = in.readString();
drivetype = in.readString();
seller_type = in.readString();
seller_name = in.readString();
website = in.readString();
city = in.readString();
state = in.readString();
year = in.readInt();
price = in.readInt();
mileage = in.readInt();
cylinders = in.readInt();
distance = in.readDouble();
images = in.createStringArrayList();
one_owner = in.readByte() != 0;
clean_title = in.readByte() != 0;
index = in.readInt();
}

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

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

public String capitalizeLetters(String input)
{
String[] array = input.split(" ");
String output = "";
int n = array.length;
for(int i=0;i<n;i++)
{
String cap = array[i].substring(0, 1).toUpperCase() + array[i].substring(1);
output += cap;
}
return output;
}

public void makeHashMap()
{
String vehicle_title = Integer.toString(this.year) + this.make + this.model + this.trim;
String vehicle_information = NumberFormat.getIntegerInstance().format(this.mileage) + " miles | " + this.color + " | " + this.condition + " | $" + NumberFormat.getIntegerInstance().format(this.price);
String dealer_name = this.seller_name;
String location = Double.toString(this.distance) + " mi. | " + this.city + ", " + this.state;
String first_img = this.images.get(0);

this.listview_hashmap.put("title", vehicle_title);
this.listview_hashmap.put("information", vehicle_information);
this.listview_hashmap.put("dealer", dealer_name);
this.listview_hashmap.put("distance", location);
this.listview_hashmap.put("first_image", first_img);
}

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

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(make);
dest.writeString(model);
dest.writeString(trim);
dest.writeString(vin);
dest.writeString(color);
dest.writeString(condition);
dest.writeString(transmission);
dest.writeString(engine);
dest.writeString(drivetype);
dest.writeString(seller_type);
dest.writeString(seller_name);
dest.writeString(website);
dest.writeString(city);
dest.writeString(state);
dest.writeInt(year);
dest.writeInt(price);
dest.writeInt(mileage);
dest.writeInt(cylinders);
dest.writeDouble(distance);
dest.writeStringList(images);
dest.writeByte((byte) (one_owner ? 1 : 0));
dest.writeByte((byte) (clean_title ? 1 : 0));
dest.writeInt(index);
}
}

Parcelable Class with list of a custom objects

it is because fechas is an ArrayList and not an Array of FechasReservasZonas. In this case you should be using

putParcelableArrayList instead of putParcelableArray

Here you can find the documentation

Making ArrayList of custom objects parcelable

Use writeTypedList and readTypedList.

parcel.writeTypedList(yourList);

and

parcel.readTypedList(yourList, YourParcelable.CREATOR);

Notice how you pass in the CREATOR as an argument for reading the list back.

How to make my Custom Model Parcelable with custom object in it's Constructor

if UserModel is Parcelable, you can use writeParcelable to write the object and readParcelable to read it back. E.g.

dest.writeParcelable(COMMENT_ACTOR, flages);

to write, and

COMMENT_ACTOR = source.readParcelable(UserModel.class.getClassLoader());

to read it back.

Problems with parcelable custom object - Android

After the suggestion of @BVantur, I solved my problem using the parceler library :
parceler library

It has been very helpful, easy to use and a good documentation! I highly recommend it.



Related Topics



Leave a reply



Submit