Accessing and Storing multiple POJO classes in Room - android

I have Multiple POJO classes as type's for the main POJO class which I am using to parse the json data using Retrofit. So I provided type converters for the first level Pojo but I'm having trouble in reading the stored data because that is not in correct format.
Here is my POJO class
#Entity(tableName = "entry")
public class Entry implements Parcelable {
#NonNull
#PrimaryKey
#SerializedName("id")
private FeedID feedId;
#SerializedName("title")
private Title EntryTitle;
#SerializedName("im:image")
private List<Image> image;
#SerializedName("summary")
private Summary summary;
public Entry(){}
public FeedID getFeedId() {
return feedId;
}
public void setFeedId(FeedID feedId) {
this.feedId = feedId;
}
public Title getEntryTitle() {
return EntryTitle;
}
public void setEntryTitle(Title entryTitle) {
this.EntryTitle = entryTitle;
}
public List<Image> getImage() {
return image;
}
public void setImage(List<Image> image) {
this.image = image;
}
public Summary getSummary() {
return summary;
}
public void setSummary(Summary summary) {
this.summary = summary;
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator<Entry>() {
#Override
public Entry createFromParcel(Parcel in) {
return new Entry(in);
}
#Override
public Entry[] newArray(int size) {
return new Entry[size];
}
};
protected Entry(Parcel in) {
feedId = (FeedID) in.readValue(FeedID.class.getClassLoader());
EntryTitle = (Title) in.readValue(Title.class.getClassLoader());
if (in.readByte() == 0x01) {
image = new ArrayList<Image>();
in.readList(image, Image.class.getClassLoader());
} else {
image = null;
}
summary = (Summary) in.readValue(Summary.class.getClassLoader());
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(feedId);
dest.writeValue(EntryTitle);
if (image == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(image);
}
dest.writeValue(summary);
}
public class Title implements Parcelable {
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
#SuppressWarnings("unused")
public final Parcelable.Creator<Title> CREATOR = new Parcelable.Creator<Title>() {
#Override
public Title createFromParcel(Parcel in) {
return new Title(in);
}
#Override
public Title[] newArray(int size) {
return new Title[size];
}
};
protected Title(Parcel in) {
label = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(label);
}
}
public class Image implements Parcelable {
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
#SuppressWarnings("unused")
public final Parcelable.Creator<Image> CREATOR = new Parcelable.Creator<Image>() {
#Override
public Image createFromParcel(Parcel in) {
return new Image(in);
}
#Override
public Image[] newArray(int size) {
return new Image[size];
}
};
protected Image(Parcel in) {
label = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(label);
}
}
public class Summary implements Parcelable {
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
#SuppressWarnings("unused")
public final Parcelable.Creator<Summary> CREATOR = new Parcelable.Creator<Summary>() {
#Override
public Summary createFromParcel(Parcel in) {
return new Summary(in);
}
#Override
public Summary[] newArray(int size) {
return new Summary[size];
}
};
protected Summary(Parcel in) {
label = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(label);
}
}
public class FeedID implements Parcelable {
private Attributes attributes;
public Attributes getAttributes() {
return attributes;
}
public void setAttributes(Attributes attributes) {
this.attributes = attributes;
}
#SuppressWarnings("unused")
public final Parcelable.Creator<FeedID> CREATOR = new Parcelable.Creator<FeedID>() {
#Override
public FeedID createFromParcel(Parcel in) {
return new FeedID(in);
}
#Override
public FeedID[] newArray(int size) {
return new FeedID[size];
}
};
protected FeedID(Parcel in) {
attributes = (Attributes) in.readValue(Attributes.class.getClassLoader());
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(attributes);
}
}
public class Attributes implements Parcelable {
#SerializedName("im:id")
private String id;
public String getIm() {
return id;
}
public void setIm(String im) {
this.id = im;
}
#SuppressWarnings("unused")
public final Parcelable.Creator<Attributes> CREATOR = new Parcelable.Creator<Attributes>() {
#Override
public Attributes createFromParcel(Parcel in) {
return new Attributes(in);
}
#Override
public Attributes[] newArray(int size) {
return new Attributes[size];
}
};
protected Attributes(Parcel in) {
id = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
}
}
}
and this is my TypeConverter class
public class RoomTypeConverters {
#TypeConverter
public static String toString(Entry.Title value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
#TypeConverter
public static Entry.Title toTitle(String value) {
Type listType = new TypeToken<Entry.Title>() {
}.getType();
return new Gson().fromJson(value, listType);
}
#TypeConverter
public static String toString(Entry.FeedID value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
#TypeConverter
public static Entry.FeedID toFeedID(String value) {
Type listType = new TypeToken<Entry.FeedID>() {
}.getType();
return new Gson().fromJson(value, listType);
}
#TypeConverter
public static String toString(Entry.Summary value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
#TypeConverter
public static Entry.Summary toSummary(String value) {
Type listType = new TypeToken<Entry.Summary>() {
}.getType();
return new Gson().fromJson(value, listType);
}
#TypeConverter
public static String toString(List<Entry.Image> value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
#TypeConverter
public static List<Entry.Image> toImage(String value) {
Type listType = new TypeToken<Entry.Summary>() {
}.getType();
return new Gson().fromJson(value, listType);
}
}
Do I have to create multiple POJO's like that only for one field? Do we have any other alternative?

Yes, to save a POJO you have to define a class for it (either inner or normal class).
But what I understand from your data schema is that you have a possibly complex data store server side and you want to use a subset of that data in your app. Your POJO can be simplified so you can create a Class called EntryRecord for example and define a simple setter and getter for it like this:
#Entity(tableName = "entry")
public class EntryRecord {
#NonNull
#PrimaryKey
#SerializedName("id")
private String feedId;
#SerializedName("title")
private StringEntryTitle;
#SerializedName("im:image")
private String[] image;
#SerializedName("summary")
private String summary;
public EntryRecord(Entry entry){
//Resolve primitive values from Entry class attributes..
}
public Entry getEntry(){
Entry entry = new Entry();
//Resolve entry values from primitive ones...
return entry ;
}
}
, now all you have to do is to use this class to save and restore your data, you can event make your DAO abstract to convert your POJO before save and vice versa.
P.S: if you don't have any use for such complex Schema with so many single variable classes I really advise you to define custom GSON serializer/deserializer to convert the complex POJO to simplified one from the beginning; removing such a complex schema entirely from your code base.

So after a little research I have found a annotation for which if you have multiple inner classes room will take care of it and you don't have to create any TypeConverters for it.
#Embedded Can be used as an annotation on a field of an Entity or Pojo to signal that nested fields (i.e. fields of the annotated field's class) can be referenced directly in the SQL queries.
For example, if you have 2 classes:
public class Coordinates {
double latitude;
double longitude;
}
public class Address {
String street;
#Embedded
Coordinates coordinates;
}
Room will consider latitude and longitude as if they are fields of the Address class when mapping an SQLite row to Address.
Source : Documentation

Related

Passing nested arraylist of object from adapter to activity

I was trying to pass arraylist of nested object from a adapter to an activity, and this activity is not the activity from which the adapter is created. I am able to pass integer or any other data to it, but the arraylist of object comes as null.
public class Rate implements Parcelable{
public final static Parcelable.Creator<Rate> CREATOR = new Creator<Rate>() {
#SuppressWarnings({
"unchecked"
})
public Rate createFromParcel(Parcel in) {
return new Rate(in);
}
public Rate[] newArray(int size) {
return (new Rate[size]);
}
};
#SerializedName("header")
#Expose
private String header;
#SerializedName("body")
#Expose
private List<Body> body = null;
#SerializedName("footer")
#Expose
private String footer;
#SerializedName("type")
#Expose
private String rateCardType;
#SerializedName("rules")
#Expose
private List<Rule> rateRules = null;
protected RateCard(Parcel in) {
this.header = ((String) in.readValue((String.class.getClassLoader())));
in.readList(this.body, (Body.class.getClassLoader()));
this.footer = ((String) in.readValue((String.class.getClassLoader())));
this.rateCardType = ((String) in.readValue((String.class.getClassLoader())));
in.readList(this.rateCardRules, (Rule.class.getClassLoader()));
}
public Rate() {
}
public List<Rule> getRateCardRules() {
return rateCardRules;
}
public void setRateCardRules(List<Rule> rateCardRules) {
this.rateCardRules = rateCardRules;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public List<Body> getBody() {
return body;
}
public void setBody(List<Body> body) {
this.body = body;
}
public String getFooter() {
return footer;
}
public void setFooter(String footer) {
this.footer = footer;
}
public String getRateCardType() {
return rateCardType;
}
public void setRateCardType(String rateCardType) {
this.rateCardType = rateCardType;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(header);
dest.writeList(body);
dest.writeValue(footer);
dest.writeValue(rateCardType);
dest.writeList(rateCardRules);
}
public int describeContents() {
return 0;
}
}
I want to pass the Rule object arraylist to another activity. My Rule
class is as shown below
public class Rule implements Parcelable{
public final static Parcelable.Creator<Rule> CREATOR = new Creator<Rule>() {
#SuppressWarnings({
"unchecked"
})
public Rule createFromParcel(Parcel in) {
return new Rule(in);
}
public Rule[] newArray(int size) {
return (new Rule[size]);
}
};
#SerializedName("rule")
#Expose
private DataRows ruleData;
#SerializedName("rule_conditions")
#Expose
private List<DataRows> ruleConditions;
#SerializedName("slots")
#Expose
private List<DataRows> slots;
#SerializedName("header")
#Expose
private DataRows header;
protected Rule(Parcel in) {
in.readList(this.ruleConditions, (DataRows.class.getClassLoader()));
in.readList(this.slots, (DataRows.class.getClassLoader()));
this.ruleData = in.readParcelable((DataRows.class.getClassLoader()));
this.header = in.readParcelable((DataRows.class.getClassLoader()));
}
public Rule() {
}
public DataRows getRuleData() {
return ruleData;
}
public void setRuleData(DataRows ruleData) {
this.ruleData = ruleData;
}
public List<DataRows> getRuleConditions() {
return ruleConditions;
}
public void setRuleConditions(List<DataRows> ruleConditions) {
this.ruleConditions = ruleConditions;
}
public List<DataRows> getSlots() {
return slots;
}
public void setSlots(List<DataRows> slots) {
this.slots = slots;
}
public DataRows getHeader() {
return header;
}
public void setHeader(DataRows header) {
this.header = header;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeList(ruleConditions);
dest.writeList(slots);
dest.writeParcelable(ruleData, flags);
dest.writeParcelable(header, flags);
}
public int describeContents() {
return 0;
}
}
My DataRows class
public class DataRows implements Parcelable{
public final static Parcelable.Creator<DataRows> CREATOR = new Creator<DataRows>() {
#SuppressWarnings({
"unchecked"
})
public DataRows createFromParcel(Parcel in) {
return new DataRows(in);
}
public DataRows[] newArray(int size) {
return (new DataRows[size]);
}
};
#SerializedName("key")
#Expose
private String key;
#SerializedName("value")
#Expose
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
protected DataRows(Parcel in) {
this.key = ((String) in.readValue((String.class.getClassLoader())));
this.value = ((String) in.readValue((String.class.getClassLoader())));
}
public DataRows() {
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(key);
dest.writeValue(value);
}
public int describeContents() {
return 0;
}
}
And this is how I am trying to pass the value
Intent intent = new Intent(context, RulesDetailActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("rules", (ArrayList<? extends Parcelable>) ruleList);
bundle.putInt("current_rule_index", ruleIndex);
startActivity(context, bundle, intent);
I am getting null for the "rules" in the target activity. What is going wrong here. Can someone help.
For these kind of problem i always prefer to use Gson library. Here is my solution for this.
import gson library.
compile 'com.google.code.gson:gson:2.7'
convert your nested Arraylist to string using gson in your adapter class.
Gson gson = new Gson();
Intent intent = new Intent(context, RulesDetailActivity.class);
intent.putExtra("rules", gson.toJson(ruleList);
startActivity(intent);
after then in RulesDetailActivity class do this:
Gson gson = new Gson();
String gson = getIntent().getStringExtra("rules");
Type type = new TypeToken<List<Rule>>() {
}.getType();
ArraList<Rule> rules = gson.fromGson(gson, type);

Parcelable with List only deserialises first element

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.

Pass ArrayList of Parcelable objects throws error

I have an object with a couple of Strings, one int and another object which has 4 inner objects. All of them implementing Parcelable. In order to generate the boilerplate code, I used Parcelable plugin from Android studio.
Even though all the objects are parcelable, I'm getting the following error: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: AlbumTrackResponse
Here's how the POJOs look like:
Main object:
public class AlbumTrackResponse implements Parcelable {
private String id;
private String albumId;
private String position;
private String title;
private int rate;
private AllServices services;
public AllServices getServices() {
return services;
}
public void setServices(AllServices services) {
this.services = services;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAlbumId() {
return albumId;
}
public void setAlbumId(String albumId) {
this.albumId = albumId;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getRate() {
return rate;
}
public void setRate(int rate) {
this.rate = rate;
}
protected AlbumTrackResponse(Parcel in) {
id = in.readString();
albumId = in.readString();
position = in.readString();
title = in.readString();
rate = in.readInt();
services = (AllServices) in.readValue(AllServices.class.getClassLoader());
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(albumId);
dest.writeString(position);
dest.writeString(title);
dest.writeInt(rate);
dest.writeValue(services);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<AlbumTrackResponse> CREATOR = new Parcelable.Creator<AlbumTrackResponse>() {
#Override
public AlbumTrackResponse createFromParcel(Parcel in) {
return new AlbumTrackResponse(in);
}
#Override
public AlbumTrackResponse[] newArray(int size) {
return new AlbumTrackResponse[size];
}
};
}
Inner object with 4 objects
public class AllServices implements Parcelable {
private GigRevService gigrev;
private AppleService apple;
private GoogleService google;
private SpotifyService spotify;
protected AllServices(Parcel in) {
gigrev = (GigRevService) in.readValue(GigRevService.class.getClassLoader());
apple = (AppleService) in.readValue(AppleService.class.getClassLoader());
google = (GoogleService) in.readValue(GoogleService.class.getClassLoader());
spotify = (SpotifyService) in.readValue(SpotifyService.class.getClassLoader());
}
#Override
public int describeContents() {
return 0;
}
public GigRevService getGigrev() {
return gigrev;
}
public void setGigrev(GigRevService gigrev) {
this.gigrev = gigrev;
}
public AppleService getApple() {
return apple;
}
public void setApple(AppleService apple) {
this.apple = apple;
}
public GoogleService getGoogle() {
return google;
}
public void setGoogle(GoogleService google) {
this.google = google;
}
public SpotifyService getSpotify() {
return spotify;
}
public void setSpotify(SpotifyService spotify) {
this.spotify = spotify;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(gigrev);
dest.writeValue(apple);
dest.writeValue(google);
dest.writeValue(spotify);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<AllServices> CREATOR = new Parcelable.Creator<AllServices>() {
#Override
public AllServices createFromParcel(Parcel in) {
return new AllServices(in);
}
#Override
public AllServices[] newArray(int size) {
return new AllServices[size];
}
};
}
The inner objects from here contain just string items.
Here's how I pass the ArrayList to the bundle:
bundle.putParcelableArrayList(MediaPlayerService.TRACK_LIST, trackList);
I'm passing the items from an Activity to a Service. Any ideas why I'm getting this error?
EDIT: Implementation of service classes
public class GoogleService implements Parcelable {
private String name;
private String uri;
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected GoogleService(Parcel in) {
name = in.readString();
uri = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(uri);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<GoogleService> CREATOR = new Parcelable.Creator<GoogleService>() {
#Override
public GoogleService createFromParcel(Parcel in) {
return new GoogleService(in);
}
#Override
public GoogleService[] newArray(int size) {
return new GoogleService[size];
}
};
}
This looks extremly strange
this.services = in.readParcelable(getClass().getClassLoader());
You are pointing out to the wrong class loader. You have to use it like this
this.services = (AllServices)in.readParcelable(AllServices.class.getClassLoader());
Besides that, I am always using this site http://www.parcelabler.com/ to quickly generate my Parceables. Or you could use it like this
services = (AllServices) in.readValue(AllServices.class.getClassLoader());
Here:
protected AllServices(Parcel in) { this.gigrev = in.readParcelable(getClass().getClassLoader());
this.apple = in.readParcelable(getClass().getClassLoader());
this.google = in.readParcelable(getClass().getClassLoader());
this.spotify = in.readParcelable(getClass().getClassLoader()); }
Replace it with
protected AllServices(Parcel in) { this.gigrev = in.readParcelable(GigRevService.class.getClassLoader());
this.apple = in.readParcelable(AppleService.class.getClassLoader());
this.google = in.readParcelable(GoogleService.class.getClassLoader());
this.spotify = in.readParcelable(SpotifyService.class.getClassLoader()); }
And replace:
this.services = in.readParcelable(getClass().getClassLoader());
With:
this.services = in.readParcelable(AllServices.class.getClassLoader());
Also can you show the GoogleService etc classes? Each inner object's class must have a Parcelable creator also and implement the Parcelable interface as well.

Parcelable inheritance in android caused ClassCastExeption

i have a Parent class implementing parcelable and a child extending parent also implementing parcelable. My code is attached below. I get a runtime ClassCastException. What am I missing?
Thanks,
Parent Class:
public class Follower implements Parcelable{
private long id;
private String fullName;
public Follower() {
}
public Follower(String fullName) {
this.fullName = fullName;
}
public long getId(){
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getFullName());
}
protected Follower(Parcel in){
setFullName(in.readString());
}
public static final Parcelable.Creator<Follower> CREATOR =
new Parcelable.Creator<Follower>() {
public Follower createFromParcel(Parcel in) {
return new Follower(in);
}
public Teen[] newArray(int size) {
return new Teen[size];
}
};
}
The Child Class
public class Teen extends Follower
implements Parcelable{
public Teen(){
super();
}
public Teen( String fullName, String birthDate) {
super(fullName);
this.birthDate = birthDate;
}
private String birthDate;
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate){
this.birthDate = birthDate;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString (birthDate);
}
private Teen(Parcel in){
super(in);
birthDate = in.readString();
}
public static final Parcelable.Creator<Teen> CREATOR =
new Parcelable.Creator<Teen>() {
public Teen createFromParcel(Parcel in) {
return new Teen(in);
}
public Teen[] newArray(int size) {
return new Teen[size];
}
};
}
On the server, I create a Teen/Follower like below. The teen and follower clasess are copied to the server without the parcelable implementation.
public Follower getData()
{
if (logic to see if the user is a teen){
Teen t = new Teen( "Full Name", "1:1:1960");
return t;
}
else
{
Follower f = new Follower("Full Name");
return f;
}
}
On the client
I do get the Follower in the client code. I have checked by accessing the Follower class methods. It works. However when I do something like this I get a ClassCastException at runtime.
if(logic to see if it is a teen)
{
Teen t = (Teen) follower;
}
I am sure it is something small that I am missing but am at loss. Any help will be appreciated. Thanks,
Change this:
public class Teen extends Follower
implements Parcelable{
to this:
public class Teen extends Follower{
You don't have to reimplement the parcelable in child, because it inherit from the parent. I'm not sure, but when you create a Teen it implements it's own parcelable data-type, and it isn't in hierarchical structure with it's parent parcelable data-type.

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

Categories

Resources