Parcelable does not unmarshall nested objects - android

I am including the whole structure below so you can see what I have done. But it is not working. When I send a NutHouse object across activities, the NutHouse arrives but the ArrayList is empty.
public class NutHouse implements Parcelable{
Safety safety = Safety.NICE;
String name;
String address;
ArrayList<Dog> dogs;
protected NutHouse(Parcel in) {
safety = in.readParcelable(Safety.class.getClassLoader());
name = in.readString();
address = in.readString();
dogs = in.createTypedArrayList(Dog.CREATOR);
mice = in.createTypedArrayList(Mouse.CREATOR);
}
public static final Creator<NutHouse> CREATOR = new Creator<NutHouse>() {
#Override
public NutHouse createFromParcel(Parcel in) {
return new NutHouse(in);
}
#Override
public NutHouse[] newArray(int size) {
return new NutHouse[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(safety, flags);
dest.writeString(name);
dest.writeString(address);
dest.writeTypedList(dogs);
dest.writeTypedList(mice);
}
}
class Dog implements Parcelable{
String name;
String owner;
ArrayList<Show> shows;
HashMap<String,String> friends;
protected Dog(Parcel in) {
name = in.readString();
owner = in.readString();
shows = in.createTypedArrayList(Show.CREATOR);
}
public static final Creator<Dog> CREATOR = new Creator<Dog>() {
#Override
public Dog createFromParcel(Parcel in) {
return new Dog(in);
}
#Override
public Dog[] newArray(int size) {
return new Dog[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(owner);
dest.writeTypedList(shows);
}
}
class Show implements Parcelable{
String address;
int placement;
protected Show(Parcel in) {
address = in.readString();
placement = in.readInt();
}
public static final Creator<Show> CREATOR = new Creator<Show>() {
#Override
public Show createFromParcel(Parcel in) {
return new Show(in);
}
#Override
public Show[] newArray(int size) {
return new Show[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(address);
dest.writeInt(placement);
}
}
enum Safety implements Parcelable{
NICE,PET,WILD;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(final Parcel dest, final int flags) {
dest.writeInt(ordinal());
}
public static final Parcelable.Creator<Safety> CREATOR = new Parcelable.Creator<Safety>() {
#Override
public Safety createFromParcel(final Parcel source) {
return Safety.values()[source.readInt()];
}
#Override
public Safety[] newArray(final int size) {
return new Safety[size];
}
};
}

Related

Save List<Object> to instance state with Parcelable

I have the following models:
GitItem:
public class GitItem implements Serializable, Parcelable {
public int id;
public String name;
public String full_name;
public GitOwner owner;
public GitItem() {
}
public GitItem(Parcel in) {
id = in.readInt();
name = in.readString();
full_name = in.readString();
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags){
out.writeInt(id);
out.writeString(name);
out.writeString(full_name);
}
public static final Parcelable.Creator<GitItem> CREATOR = new Parcelable.Creator<GitItem>(){
#Override
public GitItem createFromParcel(Parcel source) {
return new GitItem(source);
}
#Override
public GitItem[] newArray(int size) {
return new GitItem[size];
}
};
}
and GitOwner:
public class GitOwner implements Serializable, Parcelable {
public String avatar_url;
public GitOwner(Parcel in) {
avatar_url = in.readString();
}
public GitOwner() {
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
}
public static final Parcelable.Creator<GitOwner> CREATOR = new Parcelable.Creator<GitOwner>(){
#Override
public GitOwner createFromParcel(Parcel source) {
return new GitOwner(source);
}
#Override
public GitOwner[] newArray(int size) {
return new GitOwner[size];
}
};
}
and then in MainActivity.java I have a List<GitItem> data; which is bound to my RecyclerView.
Basically what I am trying to achieve, is to store current state of my List<GitItem> when I change Activity or simply rotate device. Unfortunately, even though I have implemented Parcelable (as suggested by other posts), I was unable to store the instance.
Any help in this matter would be highly appreciated.
You have not implemented the complete body of Parcelable functions i.e writeToParcel in GitOwner and GitItem class
In GitOwner class
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(avatar_url);
// add this line
}
and inside GitItem use writeParcelable to write and readParcelable to read GitItem object otherwise it won't be persisted and restored
public GitItem(Parcel in) {
id = in.readInt();
name = in.readString();
full_name = in.readString();
owner = in.readParcelable(GitItem.class.getClassLoader());
// Add line to read owner object
}
public void writeToParcel(Parcel out, int flags){
out.writeInt(id);
out.writeString(name);
out.writeString(full_name);
out.writeParcelable(owner , flags);
// Add line to write owner object
}

Why is java.lang.Integer ignored in auto Parcelable implementation by Android Studio?

This is the automatic Parcelable implementation generated by Android Studio. It somehow, always ignores resultCode which is of type Integer
public class TestParceable implements Parcelable {
private String message;
private Integer resultCode; //an Integer
protected TestParceable(Parcel in) {
message = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(message);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<TestParceable> CREATOR = new Creator<TestParceable>() {
#Override
public TestParceable createFromParcel(Parcel in) {
return new TestParceable(in);
}
#Override
public TestParceable[] newArray(int size) {
return new TestParceable[size];
}
};
}
On the other hand, if I change the type of resultCode to int, the automatic Parcelable implementation considers it.
public class TestParceable implements Parcelable {
private String message;
private int resultCode; //an int
protected TestParceable(Parcel in) {
message = in.readString();
resultCode = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(message);
dest.writeInt(resultCode);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<TestParceable> CREATOR = new Creator<TestParceable>() {
#Override
public TestParceable createFromParcel(Parcel in) {
return new TestParceable(in);
}
#Override
public TestParceable[] newArray(int size) {
return new TestParceable[size];
}
};
Am I missing something here or is this and Android Studio bug?
It's a bug (https://code.google.com/p/android/issues/detail?id=233034) which is fixed for Studio 2.4.

RuntimeException: Parcel: unable to marshal value android

I want to send model object to another activity,which contains list refer to another model
public class row_my_bookings implements Parcelable {
String BookingID;
ArrayList<MainService> list_of_mainservice;
public row_my_bookings(Parcel in) {
String[] data = new String[3];
in.readStringArray(data);
this.list_of_mainservice = in.readArrayList(null);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeList(this.list_of_mainservice); // Error shows in this line
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public row_my_bookings createFromParcel(Parcel in) {
return new row_my_bookings(in);
}
public row_my_bookings[] newArray(int size) {
return new row_my_bookings[size];
}
};
}
row_main_services model class
public class row_main_services implements Parcelable{
String ServiceId,
public MainService(Parcel in) {
String[] data = new String[3];
in.readStringArray(data);
this.id = in.readString();
this.name=in.readString();
if (in.readByte() == 0x01) {
list_child_services = new ArrayList<row_child_services>();
in.readList(list_child_services, row_child_services.class.getClassLoader());
} else {
list_child_services = null;
}
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.name);
if (list_child_services == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(list_child_services);
}
}
public static final Parcelable.Creator<MainService> CREATOR = new Parcelable.Creator<MainService>() {
public MainService createFromParcel(Parcel in) {
return new MainService(in);
}
public MainService[] newArray(int size) {
return new MainService[size];
}
};
Third module
public class row_child_services implements Parcelable{
String subId,subName;
public row_child_services(Parcel in) {
String[] data = new String[3];
in.readStringArray(data);
this.subId = in.readString();
this.subName = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.subId);
dest.writeString(this.subName);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public row_child_services createFromParcel(Parcel in) {
return new row_child_services(in);
}
public row_child_services[] newArray(int size) {
return new row_child_services[size];
}
};
I am sending object like following way
list_Bookings=new ArrayList<row_my_bookings>(rowItems);
intentBookingWindow.putParcelableArrayListExtra("BookingObject", list_Bookings);
the row_my_bookings class implements Parcelable but i guess MainService class does not implemented Parcelable and thats your problem. you must make this class Parcelable too.
I recomand you to change your model like this :
You have imported "MainService" class which is not the class you send later. I guess you must change this class to row_main_services and then reconsider your Parcelable implementations ;)
public class row_my_bookings implements Parcelable {
String BookingID;
ArrayList<row_main_services> list_of_mainservice; // i guess you must change this line
protected row_my_bookings(Parcel in) {
BookingID = in.readString();
if (in.readByte() == 0x01) {
list_of_mainservice = new ArrayList<MainService>();
in.readList(list_of_mainservice, MainService.class.getClassLoader());
} else {
list_of_mainservice = null;
}
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(BookingID);
if (list_of_mainservice == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(list_of_mainservice);
}
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<row_my_bookings> CREATOR = new Parcelable.Creator<row_my_bookings>() {
#Override
public row_my_bookings createFromParcel(Parcel in) {
return new row_my_bookings(in);
}
#Override
public row_my_bookings[] newArray(int size) {
return new row_my_bookings[size];
}
};
}
clss row_main_services:
public class row_main_services implements Parcelable {
String ServiceId,
ArrayList<row_child_services> list_row_child_services;
protected row_main_services(Parcel in) {
if (in.readByte() == 0x01) {
list_row_child_services = new ArrayList<row_child_services>();
in.readList(list_row_child_services, row_child_services.class.getClassLoader());
} else {
list_row_child_services = null;
}
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
if (list_row_child_services == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(list_row_child_services);
}
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<row_main_services> CREATOR = new Parcelable.Creator<row_main_services>() {
#Override
public row_main_services createFromParcel(Parcel in) {
return new row_main_services(in);
}
#Override
public row_main_services[] newArray(int size) {
return new row_main_services[size];
}
};
}
And here is your third class:
public class row_child_services implements Parcelable {
String subId;
String subName;
protected row_child_services(Parcel in) {
subId = in.readString();
subName = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(subId);
dest.writeString(subName);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<row_child_services> CREATOR = new Parcelable.Creator<row_child_services>() {
#Override
public row_child_services createFromParcel(Parcel in) {
return new row_child_services(in);
}
#Override
public row_child_services[] newArray(int size) {
return new row_child_services[size];
}
};
}
And about the last error you've got, I suggest you to take a look at this answer.

How to parcelable an object with an array of another object

I'm trying to do a Parcelable Object to pass data between activities. With the primary variables I don't have issues, but now I need to pass an array of another object, and I don't know how to do it. I'm searching for some examples, but I didn't find a similar case to my problem.
This is my source code of the principal object:
public class Quiz implements Parcelable {
int event_id;
String name;
String business_unit;
int functional_area_business; // 0 unchecked, 1 checked
int functional_area_support; // 0 unchecked, 1 checked
Answer [] list_answers;
//GETTERS AND SETTERS
...
//
public static final Parcelable.Creator<Quiz> CREATOR = new Parcelable.Creator<Quiz>() {
public Quiz createFromParcel(Parcel in) {
return new Quiz(in);
}
public Quiz[] newArray(int size) {
return new Quiz[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(event_id);
dest.writeString(name);
dest.writeString(business_unit);
dest.writeInt(functional_area_business);
dest.writeInt(functional_area_support);
dest.writeArray(list_answers);
}
private Quiz(Parcel in) {
event_id = in.readInt();
name = in.readString();
business_unit = in.readString();
functional_area_business = in.readInt();
functional_area_support = in.readInt();
}
}
The other class is the next.
public class Answer {
int answer_id;
String value;
}
If someone could tell me what I need to modify, I will be gratefully.
Use an ArrayList instead of an Array and make Answer class Parceable then update your code to the following:
public class Quiz implements Parcelable {
int event_id;
String name;
String business_unit;
int functional_area_business; // 0 unchecked, 1 checked
int functional_area_support; // 0 unchecked, 1 checked
List<Answer > list_answers;
//GETTERS AND SETTERS
...
//
public static final Parcelable.Creator<Quiz> CREATOR = new Parcelable.Creator<Quiz>() {
public Quiz createFromParcel(Parcel in) {
return new Quiz(in);
}
public Quiz[] newArray(int size) {
return new Quiz[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(event_id);
dest.writeString(name);
dest.writeString(business_unit);
dest.writeInt(functional_area_business);
dest.writeInt(functional_area_support);
dest.writeTypedList(list_answers);
}
private Quiz(Parcel in) {
event_id = in.readInt();
name = in.readString();
business_unit = in.readString();
functional_area_business = in.readInt();
functional_area_support = in.readInt();
list_answers = new ArrayList<Answer>();
in.readTypedList(list_answers , Answer.CREATOR);
}
}
And this is the Parceable Answer:
public class Answer implements Parcelable {
int answer_id;
String value;
public static final Parcelable.Creator<Answer> CREATOR = new Parcelable.Creator<Answer>() {
public Answer createFromParcel(Parcel in) {
return new Answer(in);
}
public Answer[] newArray(int size) {
return new Answer[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(answer_id);
dest.writeString(value);
}
private Answer(Parcel in) {
answer_id = in.readInt();
value = in.readString();
}
}

Android Intent Parcelable: Class not found when unmarshalling

I looked all answers to question "Class not found when unmarshalling" in the Stackoverflow, but I don't found solution to my situation. I tried any variants but didn't work.
I get following error:
Here my Classes:
Class one:
public class Class1 implements Parcelable, Serializable {
private static final long serialVersionUID = -3892107077759983950L;
private long id;
private ArrayList<Class2> details;
public Class1(long id, ArrayList<Class2> details) {
this.id = id;
this.details = details;
}
public Class1(Parcel in) {
this.id = in.readLong();
details = new ArrayList<Class2>((Collection<? extends Class2>) Arrays.asList(in.readParcelableArray(Class2.class.getClassLoader())));
// details = (ArrayList<OrderDetail>)in.readSerializable();
// details = in.readArrayList(Class2.class.getClassLoader());
// in.readList(details, Class2.class.getClassLoader());
// in.readTypedList(details, Class2.CREATOR);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
// dest.writeSerializable(details);
// dest.writeList(details);
// dest.writeTypedList(details);
dest.writeParcelableArray(ordDetailListToArr(), flags);
}
#Override
public int describeContents() { return 0; }
public static final Parcelable.Creator<Class1> CREATOR
= new Parcelable.Creator<Class1>() {
public Class1 createFromParcel(Parcel in) {
return new Class1(in);
}
public Class1[] newArray(int size) {
return new Class1[size];
}
};
}
Class second:
public class Class2 implements Parcelable, Serializable {
private static final long serialVersionUID = 3242734374178052427L;
private long orderId;
private Class3 Class3;
public Class2(long orderId, Class3 Class3) {
this.orderId = orderId;
this.Class3 = Class3;
}
private Class2(Parcel in) {
this.orderId = in.readLong();
this.Class3 = (Class3) in.readParcelable(Class3.class.getClassLoader());
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(orderId);
dest.writeParcelable(Class3, flags);
}
#Override
public int describeContents() { return 0;}
public static final Parcelable.Creator<Class2> CREATOR
= new Parcelable.Creator<Class2>() {
public Class2 createFromParcel(Parcel in) {
return new Class2(in);
}
public Class2[] newArray(int size) {
return new Class2[size];
}
};
}
Class third:
public class Class3 extends Class4 implements Cloneable, Serializable {
private static final long serialVersionUID = 8712386538880552241L;
private int count;
public Class3(Class4 Class4, int count) {
super(Class4.getId(), Class4.getName());
this.count = count;
}
private Class3(Parcel in) {
super(in);
this.count = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(count);
}
#Override
public int describeContents() { return 0;}
public static final Parcelable.Creator<Class3> CREATOR
= new Parcelable.Creator<Class3>() {
public Class3 createFromParcel(Parcel in) {
return new Class3(in);
}
public Class3[] newArray(int size) {
return new Class3[size];
}
};
}
class fourth:
public class Class4 implements Parcelable, Serializable {
private static final long serialVersionUID = -8394588748958519736L;
private long id;
private String name;
public Class4(long id, String name) {
this.id = id;
this.name = name;
}
public Class4(Parcel in) {
this.id = in.readLong();
this.name = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(name);
}
#Override
public int describeContents() { return 0;}
public static final Parcelable.Creator<Class4> CREATOR
= new Parcelable.Creator<Class4>() {
public Class4 createFromParcel(Parcel in) {
return new Class4(in);
}
public Class4[] newArray(int size) {
return new Class4[size];
}
};
}
I used Serializable in all classes for exchange(read/write object) data via Socket channel.
I passed data from my first activity to second activity following way:
First Activity:
Class1 class1 = ...;
Intent secondActivity = new Intent(FirstActivity.this, SecondActivity.class);
orderedProductsActivity.putExtra("mydata", (Parcelable)class1);
startActivity(secondActivity);
Second Activity:
Class1 class1 = (Class1) getIntent().getParcelableExtra("mydata");
I had this issue in the past, in my case it was related with ArrayList, can you try to do:
array = (ArrayList<Long>) in.readSerializable();
and
dest.writeSerializable(array);
instead of using writeParcelableArray

Categories

Resources