I would like to not reload RecyclerView after screen rotation. I found that I need to store/restore List from Adapter. Isn't it ?
But there is problem:
Found java.util.List<Department> requried java.util.ArrayList<?extends android.os.Parcelable>
When I try to put list in the bundle:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList("key", mAdapter.getList());
}
mAdapter.getList() return the List<Department> from the Adapter of RecyclerView.
But I had implemented Parcelable inside Department model class:
#Parcel
public class Department implements UrlInterface,Parcelable {
#SerializedName("department_id")
#Expose
String departmentId;
#SerializedName("short_name")
#Expose
String shortName;
#Expose
String url;
#Expose
HashMap<Integer, Category> categories;
public Department() {}
protected Department(android.os.Parcel in) {
departmentId = in.readString();
shortName = in.readString();
url = in.readString();
}
public static final Creator<Department> CREATOR = new Creator<Department>() {
#Override
public Department createFromParcel(android.os.Parcel in) {
return new Department(in);
}
#Override
public Department[] newArray(int size) {
return new Department[size];
}
};
public String getDepartmentId() { return departmentId; }
public void setDepartmentId(String departmentId) { this.departmentId = departmentId; }
public String getShortName() { return shortName; }
public void setShortName(String shortName) { this.shortName = shortName; }
#Override
public String getUrl() { return url; }
#Override
public String getFullName() { return shortName; }
public void setUrl(String url) { this.url = url; }
public HashMap<Integer, Category> getCategories() { return categories; }
#Override
public String toString() { return shortName; }
#Override
public String getImageUrl() { return null; }
#Override
public int describeContents() { return 0; }
#Override
public void writeToParcel(android.os.Parcel dest, int flags) {
dest.writeString(departmentId);
dest.writeString(shortName);
dest.writeString(url);
}
}
What is wrong ?
ArrayList is a subclass of List, casting from List to ArrayList....bad idea...and it will create problems, especially with parcelable stuffs.
So the quick solution is to do:
outState.putParcelableArrayList("key", new ArrayList<Department>(mAdapter.getList()));.
The above solution did not work for me and continued to throw error. The below solution, provided as hind by Android Studio worked for me-
outState.putParcelableArrayList("message_list", (ArrayList<? extends Parcelable>) messageList);
Just in case someone else also tumbles upon this thread searching for similar solution!
Related
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
I am new to Android and I am developing app which has server side functionality. I am getting response in JSON format.
My response is shown as this image.
I know how to parse json using Volley but I don't know hot to parse using GSON. Previous code of my app was written by some one else. Now I have to complete this code. but I do not know how he getting data from JSON string.
I need JSON arrays in different activity. Array response:
image
Here is some snaps of my code.
Code for adapter for activity one
topicListAdapter = new TopicListAdapter(TopicActivity.this,
myCourseListMain. getCourseArrayList().get(Integer.parseInt(course_position)).
getTopicListMain().getTopicDetailsArrayList(), flag);
listAlltopics.setAdapter(topicListAdapter);
in which I got list of topics
here is code for second activity list adapter
lessionListAdapter = new LessionListAdapter(LessionActivity.this,
myCourseListMain. getCourseArrayList(). get(Integer.parseInt(course_position)).
getTopicListMain().getTopicDetailsArrayList().get(Integer.parseInt(topic_position)).getLessionArrayList(), flag);
by this code i got array of lession in second activity
Now I want sublession array in third activity but I don't know how to get it.
Here is what I tried
lessionListAdapter = new DummyAdapter(DummyTopicList.this,
myCourseListMain . getCourseArrayList(). get(Integer.parseInt(course_position)).
getTopicListMain() . getTopicDetailsArrayList() .get(Integer.parseInt(topic_position)).
getLessionLIstMain() .getLessionLIstDetailArrayList().get(Integer.parseInt(lession_position)). , flag);
listAlllessions.setAdapter(lessionListAdapter);
Here are some other classes which helpful to you for understand
public class MyCourseListMain {
#SerializedName("data")
private ArrayList<Course> courseArrayList;
public ArrayList<Course> getCourseArrayList() {
return courseArrayList;
}
public void setCourseArrayList(ArrayList<Course> courseArrayList) {
this.courseArrayList = courseArrayList;
}
}
class for course
public class Course {
#SerializedName("img")
private String img;
#SerializedName("title")
private String title;
#SerializedName("institute_id")
private String institute_id;
#SerializedName("institute_name")
private String institute_name;
#SerializedName("expired")
private String expired;
#SerializedName("status")
private String status;
#SerializedName("subscribe_box")
private String subscribe_box;
#SerializedName("expire_on")
private String expire_on;
#SerializedName("item_id")
private String item_id;
#SerializedName("rated")
private String rated;
private TopicListMain topicListMain;
public String getRated() {
return rated;
}
public void setRated(String rated) {
this.rated = rated;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getInstitute_id() {
return institute_id;
}
public void setInstitute_id(String institute_id) {
this.institute_id = institute_id;
}
public String getInstitute_name() {
return institute_name;
}
public void setInstitute_name(String institute_name) {
this.institute_name = institute_name;
}
public String getExpired() {
return expired;
}
public void setExpired(String expired) {
this.expired = expired;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getSubscribe_box() {
return subscribe_box;
}
public void setSubscribe_box(String subscribe_box) {
this.subscribe_box = subscribe_box;
}
public String getExpire_on() {
return expire_on;
}
public void setExpire_on(String expire_on) {
this.expire_on = expire_on;
}
public String getItem_id() {
return item_id;
}
public void setItem_id(String item_id) {
this.item_id = item_id;
}
public TopicListMain getTopicListMain() {
return topicListMain;
}
public void setTopicListMain(TopicListMain topicListMain) {
this.topicListMain = topicListMain; } }
class for topiclist_main
public class TopicListMain {
#SerializedName("data")
private ArrayList<TopicDetails> topicDetailsArrayList;
public ArrayList<TopicDetails> getTopicDetailsArrayList() {
return topicDetailsArrayList;
}
public void setTopicDetailsArrayList(ArrayList<TopicDetails> topicDetailsArrayList) {
this.topicDetailsArrayList = topicDetailsArrayList; }}
class for topic details
public class TopicDetails
{
#SerializedName("topic_id")
private String topic_id;
#SerializedName("title")
private String title;
#SerializedName("locked")
private String locked;
#SerializedName("lessons")
private ArrayList<Lession> lessionArrayList;
private LessionLIstMain lessionLIstMain;
public LessionLIstMain getLessionLIstMain() {
return lessionLIstMain;
}
public void setLessionLIstMain(LessionLIstMain lessionLIstMain) {
this.lessionLIstMain = lessionLIstMain;
}
public String getTopic_id() {
return topic_id;
}
public void setTopic_id(String topic_id) {
this.topic_id = topic_id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLocked() {
return locked;
}
public void setLocked(String locked) {
this.locked = locked;
}
public ArrayList<Lession> getLessionArrayList() {
return lessionArrayList;
}
public void setLessionArrayList(ArrayList<Lession> lessionArrayList) {
this.lessionArrayList = lessionArrayList; }}
https://github.com/google/gson
Make your object have same construct with your data which you got.And
YourObject val = new Gson().fromJson(new String(YourString.getBytes("ISO-8859-1"),
"UTF-8"), YourObject.class);
finally i got my solution by below code.
lessionListAdapter = new DummyAdapter(DummyTopicList.this,
myCourseListMain . getCourseArrayList(). get(Integer.parseInt(course_position)).
getTopicListMain() . getTopicDetailsArrayList() .get(Integer.parseInt(topic_position)).
getLessionArrayList().get(Integer.parseInt((lession_position))).getLessionLIstDetailArrayList() , flag);
listAlllessions.setAdapter(lessionListAdapter);
i also made some few classes to handle json array.
public class SubLessionDetail {
#SerializedName("lesson_id")
private String lession_id;
#SerializedName("title")
private String title;
#SerializedName("locked")
private String locked;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLocked() {
return locked;
}
public void setLocked(String locked) {
this.locked = locked;
}
public String getLession_id() {
return lession_id;
}
public void setLession_id(String lession_id) {
this.lession_id = lession_id;
}
}
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.
Hello I need to send List from one activity to another, I found method in parcel
readTypedList amd write TypedList
I writethem like
parcel.writeTypedList(busImages);
and try to call like
in.readTypedList(busImages,Bitmap.Creator);
but there is error in second parametr Bitmap.Creator, Do i need create my own creator or how to solve this problem?
class code:
public class ExtendBusModel extends BusModelParcelable {
private List<Bitmap> busImages;
private String Country;
public ExtendBusModel(BusModelParcelable model, List<Bitmap> busImages, String country) {
super(model, model.getCountOfPlaces(),model.getTransportClass());
this.busImages = busImages;
Country = country;
}
protected ExtendBusModel(Parcel in) {
super(in);
Log.d("read parsel buses", TestTags.TAG1);
// in.readList(busImages,List.class.getClassLoader());
in.readTypedList(busImages,Bitmap.Creator);
Log.d("read parcel coutry",TestTags.TAG1);
Country = in.readString();
Log.d("done read",TestTags.TAG1);
// super(in);
}
#Override
public void writeToParcel(Parcel parcel, int i) {
super.writeToParcel(parcel, i);
//parcel.writeList(busImages);
parcel.writeTypedList(busImages);
parcel.writeString(Country);
}
public static final Creator<ExtendBusModel> CREATOR = new Creator<ExtendBusModel>() {
#Override
public ExtendBusModel createFromParcel(Parcel in) {
return new ExtendBusModel(in);
}
#Override
public ExtendBusModel[] newArray(int size) {
return new ExtendBusModel[size];
}
};
public List<Bitmap> getBusImages() {
if(busImages == null)
return new ArrayList<Bitmap>();
return busImages;
}
public void setBusImages(List<Bitmap> busImages) {
this.busImages = busImages;
}
public String getCountry() {
return Country;
}
public void setCountry(String country) {
Country = country;
}
}
Write your CREATOR as below...this may be solve your problem.
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public ExtendBusModel createFromParcel(Parcel in) {
return new ExtendBusModel(in);
}
public ExtendBusModel[] newArray(int size) {
new ExtendBusModel[size];
}
};
I am currently trying to pass a parceablearraylist from mylogin activity to my main activity but getting a
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.muuves.introround/com.muuves.introround.activities.MainActivity}: java.lang.RuntimeException: Parcel android.os.Parcel#41ef90a8: Unmarshalling unknown type code 7536741 at offset 684
Here are my parceable objects
public class Challenge implements Parcelable {
private Integer id;
private Integer challenger_id;
private Integer friend_id;
private String artist_name;
private String song_name;
private String image_url;
private String song_url;
private String answer_url;
private int challenge_attempts_left;
private int answer;
private Person person;
private Person friend;
public Challenge() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getChallenger_id() {
return challenger_id;
}
public void setChallenger_id(Integer challenger_id) {
this.challenger_id = challenger_id;
}
public Integer getFriend_id() {
return friend_id;
}
public void setFriend_id(Integer friend_id) {
this.friend_id = friend_id;
}
public String getArtist_name() {
return artist_name;
}
public void setArtist_name(String artist_name) {
this.artist_name = artist_name;
}
public String getSong_name() {
return song_name;
}
public void setSong_name(String song_name) {
this.song_name = song_name;
}
public String getImage_url() {
return image_url;
}
public void setImage_url(String image_url) {
this.image_url = image_url;
}
public String getSong_url() {
return song_url;
}
public void setSong_url(String song_url) {
this.song_url = song_url;
}
public String getAnswer_url() {
return answer_url;
}
public void setAnswer_url(String answer_url) {
this.answer_url = answer_url;
}
public int getChallenge_attempts_left() {
return challenge_attempts_left;
}
public void setChallenge_attempts_left(int challenge_attempts_left) {
this.challenge_attempts_left = challenge_attempts_left;
}
public int getAnswer() {
return answer;
}
public void setAnswer(int answer) {
this.answer = answer;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Person getFriend() {
return friend;
}
public void setFriend(Person friend) {
this.friend = friend;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeInt(challenger_id);
dest.writeInt(friend_id);
dest.writeString(artist_name);
dest.writeString(image_url);
dest.writeString(song_url);
dest.writeString(answer_url);
dest.writeInt(challenge_attempts_left);
dest.writeInt(answer);
dest.writeParcelable(person, flags);
dest.writeParcelable(friend, flags);
}
public static final Parcelable.Creator<Challenge> CREATOR = new Parcelable.Creator<Challenge>() {
#Override
public Challenge createFromParcel(Parcel in) {
Challenge challenge = new Challenge();
challenge.setId(in.readInt());
challenge.setChallenger_id(in.readInt());
challenge.setFriend_id(in.readInt());
challenge.setArtist_name(in.readString());
challenge.setSong_name(in.readString());
challenge.setImage_url(in.readString());
challenge.setSong_url(in.readString());
challenge.setAnswer_url(in.readString());
challenge.setChallenge_attempts_left(in.readInt());
challenge.setAnswer(in.readInt());
challenge.setPerson((Person) in.readParcelable(Person.class.getClassLoader()));
challenge.setFriend((Person) in.readParcelable(Person.class.getClassLoader()));
return challenge;
}
#Override
public Challenge[] newArray(int size) {
return new Challenge[size];
}
};
}
public class Person implements Parcelable {
private int id;
private String first_name;
private String last_name;
private String image_url;
public Person(){
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirst_Name() {
return first_name;
}
public void setFirst_Name(String first_name) {
this.first_name = first_name;
}
public String getLast_Name() {
return last_name;
}
public void setLast_Name(String last_name) {
this.last_name = last_name;
}
public String getImage_url() {
return image_url;
}
public void setImage_url(String image_url) {
this.image_url = image_url;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(first_name);
dest.writeString(last_name);
dest.writeString(image_url);
}
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
#Override
public Person createFromParcel(Parcel in) {
Person person = new Person();
person.setId(in.readInt());
person.setFirst_Name(in.readString());
person.setLast_Name(in.readString());
person.setImage_url(in.readString());
return person;
}
#Override
public Person[] newArray(int size) {
return null;
}
};
}
Login activity
#Override
public void preLoadDetails(Details details) {
Intent intent = new Intent(this, MainActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("receive", details.getReceive());
intent.putExtras(bundle);
startActivity(intent);
}
MainActivity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = this.getIntent().getExtras();
ArrayList<Challenge> friends = bundle.getParcelableArrayList("receive");
mContent = new MainFragment(0);
mContent.setArguments(getIntent().getExtras());
// set the Above View
setContentView(R.layout.home_frame);
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, mContent).commit();
// set the Behind View
setBehindContentView(R.layout.menu_frame);
getSupportFragmentManager().beginTransaction()
.replace(R.id.menu_frame, new MenuFragment()).commit();
// Disable
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE);
}
Been trying to fix it for the pass day and getting no where all I know is that person parceable object in the challenge object are always null but they are not when I put them in the bundle.
Appreciate any input.
Those Integer type could be null or an int, you need to handle that situation properly.
For example I have utility functions like this :
static public Integer readInteger(Parcel in){
if(in.readInt() == 1){
return in.readInt();
}else{
return null;
}
}
static public void writeInteger(Integer value, Parcel out){
if(value != null){
out.writeInt(1);
out.writeInt(value);
}else{
out.writeInt(0);
}
}
First thing in the class Challenge you use Integer attributes and you parce "int" those are 2 diferents things.
Exemple of how i do things myself :
public Podcast(Parcel parcel) {
id = parcel.readLong();
title = parcel.readString();
subtitle = parcel.readString();
summary = parcel.readString();
duration = parcel.readString();
author = parcel.readString();
date = parcel.readString();
mp3 = parcel.readString();
podcastCategoryId = parcel.readLong();
}
#Override
public int describeContents() {
// not used
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(title);
dest.writeString(subtitle);
dest.writeString(summary);
dest.writeString(duration);
dest.writeString(author);
dest.writeString(date);
dest.writeString(mp3);
dest.writeLong(podcastCategoryId);
}
public static Creator<Podcast> CREATOR = new Creator<Podcast>() {
public Podcast createFromParcel(Parcel parcel) {
return new Podcast(parcel);
}
public Podcast[] newArray(int size) {
return new Podcast[size];
}
};
#Override
public Person[] newArray(int size) {
return null;
}
You should create there an array of that size and return it.
#Override
public Person[] newArray(int size) {
return new Person[size];
}
Solved it was actually very simple, forgot song url when i was writing to the parcel. Any when i missed that write that was why i was getting the weird exception for person object. it was expecting a person object but was getting something else. 1 day wasted oh well :(
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeInt(challenger_id);
dest.writeInt(friend_id);
dest.writeString(artist_name);
**dest.writeString(song_name);**
dest.writeString(image_url);
dest.writeString(song_url);
dest.writeString(answer_url);
dest.writeInt(challenge_attempts_left);
dest.writeInt(answer);
dest.writeParcelable(person, flags);
dest.writeParcelable(friend, flags);
}