I got 3 classes. Series, Season and Episodes.
The Series class got a list of Season objects and the Season class got a list of Episode objects.
I want to send the Series object to the other activity like this.
Intent intent = new Intent(context, OtherActivity.class);
intent.putExtra("series", (Parcelable)seriesObject);
But I get a NullPointerException.
Here are the classes that implements Parcelable.
Series class:
public class Series implements Parcelable {
private int seasonCount;
public ArrayList<Season>seasons;
private String seriesName;
private int lastSeenSeason = 0;
private int lastSeenEpisode = 0;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(seasonCount);
dest.writeTypedList(seasons);
dest.writeString(seriesName);
dest.writeInt(lastSeenSeason);
dest.writeInt(lastSeenEpisode);
}
private Series(Parcel in){
seasonCount = in.readInt();
in.readTypedList(seasons, Season.CREATOR);
seriesName = in.readString();
lastSeenSeason = in.readInt();
lastSeenEpisode = in.readInt();
}
public static final Parcelable.Creator<Series> CREATOR = new Parcelable.Creator<Series>() {
public Series createFromParcel(Parcel in) {
return new Series(in);
}
public Series[] newArray(int size) {
return new Series[size];
}
};
Season class:
public class Season implements Parcelable{
private int seasonNo;
private int episodeCount;
public ArrayList<Episode> episodes;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(seasonNo);
dest.writeInt(episodeCount);
dest.writeTypedList(episodes);
}
private Season(Parcel in){
this.seasonNo = in.readInt();
episodeCount = in.readInt();
in.readTypedList(episodes, Episode.CREATOR);
}
public static final Parcelable.Creator<Season> CREATOR = new Parcelable.Creator<Season>() {
public Season createFromParcel(Parcel in) {
return new Season(in);
}
public Season[] newArray(int size) {
return new Season[size];
}
};
and the Episode class:
public class Episode implements Parcelable{
private int episodeNo;
private boolean episodeSeen;
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(episodeNo);
dest.writeByte((byte) (episodeSeen ? 1 : 0));
}
private Episode(Parcel in){
episodeNo = in.readInt();
episodeSeen = in.readByte() != 0;
}
public static final Parcelable.Creator<Episode> CREATOR = new Parcelable.Creator<Episode>() {
public Episode createFromParcel(Parcel in) {
return new Episode(in);
}
public Episode[] newArray(int size) {
return new Episode[size];
}
};
You should initialize your arrays:
public ArrayList<Episode> episodes = new ArrayList<Episode>();
public ArrayList<Season> seasons = new ArrayList<Season>();
otherwise readTypedList will fail.
Related
I have a Parcelable object that has a list of Parcelable objects. I am trying to read that list back after it has been passed from one Activity to the next, but only the first element is "un-bundled"
public class MyBundle implements Parcelable {
private List<Data> dataList;
public static final Parcelable.Creator<MyBundle> CREATOR = new Parcelable.Creator<MyBundle>() {
public MyBundle createFromParcel(Parcel in) {
return new MyBundle(in);
}
public MyBundle[] newArray(int size) {
return new MyBundle[size];
}
};
public MyBundle() {
}
public MyBundle(Parcel in) {
//dataList = new ArrayList<>();
//in.readTypedList(dataList, Data.CREATOR);
dataList = in.createTypedArrayList(Data.CREATOR);
//BOTH have the same result
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
if (dataList != null && dataList.size() > 0) {
dest.writeTypedList(dataList);
}
}
}
The data object:
/*BaseObject has the following properties:
UUID uuid;
long databaseId;
createdDate;
modifiedDate;
*/
public class Data extends BaseObject implements Parcelable {
private String name;
private String serial;
private String location;
public Data() {}
private Data(Parcel in) {
String uuidString = in.readString();
if (uuidString == null) return; //this is null!
uuid = UUID.fromString(idString);
databaseId = in.readLong();
createdDate = new Date(in.readLong());
modifiedDate = new Date(in.readLong());
location = in.readString();
name = in.readString();
serial = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(uuid.toString());
dest.writeLong(databaseId);
dest.writeLong(createdDate.getTime());
dest.writeLong(modifiedDate.getTime());
dest.writeString(name);
dest.writeString(serial);
}
public static final Parcelable.Creator<Data> CREATOR
= new Parcelable.Creator<Data>() {
public Data createFromParcel(Parcel in) {
return new Data(in);
}
public Data[] newArray(int size) {
return new Data[size];
}
};
}
What I have tried:
Debugging - I can see the first element is read fine but the rest are return null, and they do have values when they are being written
"Android, How to use readTypedList method correctly in a Parcelable class?"
"how to properly implement Parcelable with an ArrayList?"
So this is the answer: My Data parcelable misses the location element when it creates the parcel. This obviously results in some kind of offset error when READING occurs. So the coded solution is as follows:
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(uuid.toString());
dest.writeLong(databaseId);
dest.writeLong(createdDate.getTime());
dest.writeLong(modifiedDate.getTime());
dest.writeString(location); /*HERE!*/
dest.writeString(name);
dest.writeString(serial);
}
I hope this helps someone else.
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];
}
};
}
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();
}
}
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);
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