RuntimeException: Parcel: unable to marshal value android - 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.

Related

Parcable of generic array

I generate parcelable implementation with plugin and that is the code i got.
I have a an error compilation on Metrics(Parcel in).
It probably because the generic array. How can i fix it?
The generic T can can contain String, Number or boolean only.
public class Metrics<T extends Parcelable> implements Parcelable {
private T[] yData;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedArray(this.yData, flags);
}
public Metrics() {
}
protected Metrics(Parcel in) {
this.yData = in.createTypedArray(T.CREATOR);
}
public static final Parcelable.Creator<Metrics> CREATOR = new Parcelable.Creator<Metrics>() {
#Override
public Metrics createFromParcel(Parcel source) {
return new Metrics(source);
}
#Override
public Metrics[] newArray(int size) {
return new Metrics[size];
}
};
}
You can use a List instead of an array :
public class Metrics<T extends Parcelable> implements Parcelable {
private List<T> yData;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
if (yData == null || yData.size() == 0)
dest.writeInt(0);
else {
dest.writeInt(yData.size());
final Class<?> objectsType = yData.get(0).getClass();
dest.writeSerializable(objectsType);
dest.writeList(yData);
}
}
public Metrics() {
}
protected Metrics(Parcel in) {
int size = in.readInt();
if (size == 0) {
yData = null;
} else {
Class<?> type = (Class<?>) in.readSerializable();
yData = new ArrayList<>(size);
in.readList(yData, type.getClassLoader());
}
}
public static final Parcelable.Creator<Metrics> CREATOR = new Parcelable.Creator<Metrics>() {
#Override
public Metrics createFromParcel(Parcel source) {
return new Metrics(source);
}
#Override
public Metrics[] newArray(int size) {
return new Metrics[size];
}
};
}

Parcelable does not unmarshall nested objects

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];
}
};
}

Android Parcelable usage

I have a class with the following structure:
class Example {
Integer age;
String name;
Collection<Example2>examples;
class Example2 {
Integer number;
Collection<String>strings;
}
}
How can I make this class implement Parcelable so that I can send its object across activities.
The simplest way will be to use #AutoParcel and let it handle the heavy lifting for you.
You should take a look at this thread : Android: Making a class parcelable
So your classes should be something like :
class Example implements Parcelable {
Integer age;
String name;
ArrayList<Example2> examples;
public Example(Parcel in) {
examples = new ArrayList<>();
readFromParcel(in);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeString(name);
dest.writeList(examples != null ? examples : new ArrayList());
}
private void readFromParcel(Parcel in) {
age = in.readInt();
name = in.readString();
in.readList(examples, Example2.class.getClassLoader());
}
public static final Creator<Example> CREATOR = new Creator<Example>() {
#Override
public Example createFromParcel(Parcel in) {
return new Example(in);
}
#Override
public Example[] newArray(int size) {
return new Example[size];
}
};
}
and
class Example2 implements Parcelable {
Integer number;
ArrayList<String> labels;
public Example2(Parcel in) {
labels = new ArrayList<>();
readFromParcel(in);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInteger(number);
dest.writeList(labels != null ? labels : new ArrayList());
}
#Override
public int describeContents() {
return 0;
}
private void readFromParcel(Parcel in) {
number = in.readInteger();
in.readStringList(labels);
}
public static final Creator<Example2> CREATOR = new Creator<Example2>() {
#Override
public Example2 createFromParcel(Parcel in) {
return new Example2(in);
}
#Override
public Example2[] newArray(int size) {
return new Example2[size];
}
};
}

Sending Nested Parcelable with Intent

I am trying to send a Parcelable object which also contains another Parcelable object with Intent. However, I am getting NullPointer Exception. Could you please tell me where I am doing wrong?
A.java
public class A implements Parcelable {
private ArrayList<B> var;
public A()
{
this.var = new ArrayList<B>();
}
public void addToB(B b)
{
var.add(b);
}
public ArrayList<B> getB() {
return var;
}
public void setB(ArrayList<B> b) {
this.var = b;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(this.var);
}
private A (Parcel in){
in.readTypedList(this.var, B.CREATOR);
}
public static final Parcelable.Creator<A> CREATOR = new Parcelable.Creator<A>() {
public A createFromParcel(Parcel in) {
return new A(in);
}
public A[] newArray(int size) {
return new A[size];
}
};
}
B.java
public class B implements Parcelable {
private String type;
public B(String type)
{
this.type=type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel arg0, int arg1) {
arg0.writeString(this.type);
}
private B(Parcel in) {
this.type=in.readString();
}
public static final Parcelable.Creator<B> CREATOR = new Parcelable.Creator<B>() {
public B createFromParcel(Parcel in) {
return new B(in);
}
public B[] newArray(int size) {
return new B[size];
}
};
}
I send the A object with Intent like this:
Intent i = new Intent(Bla.this, Blabla.class);
i.putExtra("info", objectA);
startActivity(i);
I receive the parcelable like this:
Intent i = getIntent();
ObjectA ci = (ObjectA)i.getParcelableExtra("info");
You have to instanciate your ArrayList< B > in :
private A (Parcel in){
var = new ArrayList<B>();
in.readTypedList(this.var, B.CREATOR);
}
Say if it works :)
You are not assigning data to var variable in constructor.
change it like
private A (Parcel in){
var=(ArrayList)in.readTypedList(this.var, B.CREATOR);
}
Edit::
Change your code like this and try
#Override
public void writeToParcel(Parcel dest, int flags) {
B[] data = new B[var.size()];
for (int i = 0; i < data.length; i++) {
data[i] = var.get(i);
}
dest.writeParcelableArray(data, flags);
}
public A(Parcel in) {
Parcelable[] parcelables = in.readParcelableArray(Thread
.currentThread().getContextClassLoader());
ArrayList<B> list = new ArrayList<B>();
for (Parcelable parcelable : parcelables) {
list.add((B) parcelable);
}
var = list;
}
you have problem with parsing the arraylist... do these changes..
private A (Parcel in){
in.readTypedList(this.var, B.CREATOR);
}
to
this.var=in.readArrayList(B.class.getClassLoader());
and
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(this.var);
}
to
dest.writeList(this.var);

How to extend android class which implements Parcelable interface?

First of all i have check this answer.
What i am trying to do is extending Location class calling it LocationPlus which has some
member variables. functionality i am trying to achieve is pass the object of LocationPlus class from one activity to another.
Here is my CREATOR
public static final Parcelable.Creator<LocationPlus> CREATOR = new Parcelable.Creator<LocationPlus>() {
#Override
public LocationPlus createFromParcel(Parcel source) {
return new LocationPlus(source);
}
#Override
public LocationPlus[] newArray(int size) {
return new LocationPlus[size];
}
};
problem i am facing is this error
Implicit super constructor Location() is undefined. Must explicitly invoke another constructor
when trying to write constructor
public LocationPlus(Parcel in) {
Someone in comment ask me to post LocationPlus class so here it is
public class LocationPlus extends Location{
private int mBattery = -1;
public LocationPlus(String locationName) {
super(locationName);
}
public LocationPlus(Location location) {
super(location);
}
public int getmBattery() {
return mBattery;
}
public void setmBattery(int mBattery) {
this.mBattery = mBattery;
}
#Override
public int describeContents() {
return 0;
}
public static final Parcelable.Creator<LocationPlus> CREATOR = new Parcelable.Creator<LocationPlus>() {
#Override
public LocationPlus createFromParcel(Parcel source) {
return new LocationPlus(source);
}
#Override
public LocationPlus[] newArray(int size) {
return new LocationPlus[size];
}
};
#Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(mBattery);
}
public LocationPlus(Parcel in) {
mBattery =in.readInt();
}
}
Parcelable, the Speed King
According to google engineers, this code will run significantly faster. One of the reasons for this is that we are being explicit about the serialization process instead of using reflection to infer it. It also stands to reason that the code has been heavily optimized for this purpose.
public abstract class BaseClass implements Parcelable {
public String FullName;
public boolean IsValidUser;
public String UserName;
public BaseClass () {
}
protected BaseClass(Parcel in) {
FullName = in.readString();
IsValidUser = in.readByte() != 0;
UserName = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(FullName);
dest.writeByte((byte) (IsValidUser ? 1 : 0));
dest.writeString(UserName);
}
}
Child class will be as follows with usage of list adding into parcelable object:
public class DerivedClass extends BaseClass {
public boolean IsSuccess;
public String Message;
public List<AnotherClass> AnotherClassObj;
public DerivedClass () {
super();
}
protected DerivedClass(Parcel in) {
super(in);
AnotherClassObj = new ArrayList<AnotherClass>();
IsSuccess = in.readByte() != 0;
Message = in.readString();
AnotherClassObj = in.readArrayList(AnotherClass.class.getClassLoader());
}
public static final Creator<DerivedClass> CREATOR = new Creator<DerivedClass>() {
#Override
public DerivedClass createFromParcel(Parcel in) {
return new DerivedClass(in);
}
#Override
public DerivedClass[] newArray(int size) {
return new DerivedClass[size];
}
};
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeByte((byte) (IsSuccess ? 1 : 0));
dest.writeString(Message);
dest.writeList(AnotherClassObj);
}
public int describeContents() {
return 0;
}
}
Another child class :
public class AnotherClass extends BaseClass {
public AnotherClass() {
super();
}
protected AnotherClass(Parcel in) {
super(in);
}
public int describeContents() {
return 0;
}
public static final Creator<AnotherClass> CREATOR = new Creator<AnotherClass>() {
#Override
public AnotherClass createFromParcel(Parcel in) {
return new AnotherClass(in);
}
#Override
public AnotherClass[] newArray(int size) {
return new AnotherClass[size];
}
};
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
}
}
In Activity:
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.putExtra("UserObject", parcelableObject);
startActivity(intent);
finish();
In receiving activity:
Bundle extras = getIntent().getExtras();
if (extras != null) {
userObject = extras.getParcelable("UserObject");
}
Hi I've do research a lot about this, but I couldn't find useful anything. I try solution below and it worked for me.
Let say your super class has only int variable named "mData".
public class Location implements Parcelable {
protected int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator<Location> CREATOR
= new Parcelable.Creator<Location>() {
public Location createFromParcel(Parcel in) {
return new Location(in);
}
public Location[] newArray(int size) {
return new Location[size];
}
};
private Location(Parcel in) {
mData = in.readInt();
}
}
Then, your extended class has only int variable named "mBattery".
public class LocationPlus extends Location {
protected int mBattery;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mBattery);
}
public static final Parcelable.Creator<LocationPlus> CREATOR
= new Parcelable.Creator<LocationPlus>() {
public LocationPlus createFromParcel(Parcel in) {
return new LocationPlus(in);
}
public LocationPlus[] newArray(int size) {
return new LocationPlus[size];
}
};
private LocationPlus(Parcel in) {
mBattery = in.readInt();
}
}
So far, LocationPlus works fine. But we don't set variable of super class. Firstly, I set super class' variables on extended class with super(..) method. But it didn't work.
private LocationPlus(Parcel in) {
super(in);
mBattery = in.readInt();
}
Instead of code above, you should set all super class' variables explicitly. Super class' variables should be protected. Final constructor should be like this:
private LocationPlus(Parcel in) {
mData = in.readIn();
mBattery = in.readInt();
}
and writeToParcel method should be like this:
public void writeToParcel(Parcel out, int flags) {
out.writeIn(mData);
out.writeInt(mBattery);
}
Try this solution:
public static final Parcelable.Creator<LocationPlus> CREATOR =
new Parcelable.Creator<LocationPlus>() {
#Override
public LocationPlus createFromParcel(Parcel in) {
Location l = Location.CREATOR.createFromParcel(in);
LocationPlus lp = new LocationPlus(l);
lp.mBattery= in.readInt();
return lp;
}
#Override
public LocationPlus[] newArray(int size) {
return new LocationPlus[size];
}
};
#Override
public void writeToParcel(Parcel parcel, int flags) {
super.writeToParcel(parcel, flags);
parcel.writeInt(mBattery);
}
According to the Android docs, there isn't a Location() constructor for the Location class. When initializing your LocationPlus class, you need to call either super(String provider) or super(Location l).
Edit: Corrected syntax
(See Location Android Doc)

Categories

Resources