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
Capture Image from Camera and Display in Activity
How to Open a Url in Android'S Web Browser from My Application
Replace Fragment Inside a Viewpager
Determining the Current Foreground Application from a Background Task or Service
What Is Android:Weightsum in Android, and How Does It Work
Android: How to Prevent the Soft Keyboard from Pushing My View Up
Android Broadcastreceiver on Startup - Keep Running When Activity Is in Background
How to Create a Custom-Shaped Bitmap Marker With Android Map API V2
Android - How to Override the "Back" Button So It Doesn't Finish() My Activity
Android Intent Filter For a Particular File Extension
"Cannot Resolve Symbol R" in Android Studio
Android Asynctask Sending Callbacks to Ui
Communicating Between a Fragment and an Activity - Best Practices
How to Add Dividers and Spaces Between Items in Recyclerview
How to Put Google Maps V2 on a Fragment Using Viewpager