android nested object parceling - android

how can we parcel nested object in an intent?. For example
lets say there is an object A which contain one string variable and one another object B. now B contain object C . C contain a list of string. so how i can parcel object A in an intent. any help on this will be appreciated. thanks in advance.
Implementation:
public static class A
{
private B ObjectB;
}
public static class B
{
private String type;
private List<C> C;
}
public static class C
{
private List<D> D;
}
public static class D
{
private String id;
private String name;
private String address;
private String email;
}
how to write parcelable for class C.
i am using
dest.writeParceable(ObjectC,flag)
For reading:
in.readParcelable(C.getClass().getClassLoader());
but its not working

You would have to implement parcelable for object B and then implement parcelable for object A. I have never done this but the above should work.
Edit
See the code snippets below which illustrates how to implement parcelable for Class C.
First implement parcelable for Class D like so:
dest.writeString(id);
dest.writeString(name);
dest.writeString(address);
dest.writeString(email);
id = in.readString();
name = in.readString();
address = in.readString();
email = in.readString();
Then implement parcelable for Class C as follows:
dest.writeList(D);
in.readList(D,this.getClass().getClassLoader());
This is untested code as I have never implemented nested parceling but worth a try. Hope that helps.

One way I have seen this done is using serializeable
eg.
if you have a variable:
Date createdAt;
Then in writeToParcel(Parcel out, int flags) you can write:
out.writeSerializable(createdAt);
To read the value back yoy would use:
createdAt = (Date) in.readSerializable();
That being said though Parcelable was specifically created because Java serialization was considered too slow. So while this works it is not a good idea to use for larger pieces of data.

Related

Parcelable for object [duplicate]

public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
mData = in.readInt();
}
}
During my Android course, the instructor used this block of code and they didn't quite explained this. How can I interpret this code? I tried reading the documentation but I failed to interpret.
This concept is called Parcelable
A Parcelable is the Android implementation of the Java Serializable. It assumes a certain structure and way of processing it. This way a Parcelable can be processed relatively fast, compared to the standard Java serialization.
To allow your custom object to be parsed to another component they need to implement the android.os.Parcelable interface. It must also provide a static final method called CREATOR which must implement the Parcelable.Creator interface.
The code you have written will be your model class.
You can use Parcelable in Activity like :
intent.putExtra("student", new Student("1")); //size which you are storing
And to get this object :
Bundle data = getIntent().getExtras();
Student student = (Student) data.getParcelable("student");
Here Student is a model class name. replace this with yours.
In simple terms Parcelable is used to send a whole object of a model class to another page.
In your code this is in the model and it is storing int value size to Parcelable object to send and retrieve in other activity.
Reference :
Tutorial 1
Tutorial 2
Tutorial 3
--> Parcelable in Android
The Bundle object which is used to pass data to Android components is a key/value store for specialized objects. It is similar to a Map but can only contain these specialized objects
You can place the following objects types into a Bundle:
String
primitives
Serializable
Parcelable
If you need to pass your customer objects via a Bundle, you should implement the Parcelable interface.
--> Implementing Parcelable
You can create a POJO class for this, but you need to add some extra code to make it Parcelable. Have a look at the implementation.
public class Student implements Parcelable{
private String id;
private String name;
private String grade;
// Constructor
public Student(String id, String name, String grade){
this.id = id;
this.name = name;
this.grade = grade;
}
// Getter and setter methods
.........
.........
// Parcelling part
public Student(Parcel in){
String[] data = new String[3];
in.readStringArray(data);
this.id = data[0];
this.name = data[1];
this.grade = data[2];
}
#override
public int describeContents(){
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] {this.id,
this.name,
this.grade});
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Student createFromParcel(Parcel in) {
return new Student(in);
}
public Student[] newArray(int size) {
return new Student[size];
}
};
}
Once you have created this class, you can easily pass objects of this class through the Intent like this, and recover this object in the target activity.
intent.putExtra("student", new Student("1","Mike","6"));
Here, the student is the key which you would require to unparcel the data from the bundle.
Bundle data = getIntent().getExtras();
Student student = data.getParcelable("student");
This example shows only String types. But, you can parcel any kind of data you want. Try it out.

Is it necessary to make members of custom classes parcelable in order to make the class parcelable

public class Movie implements Parcelable {
private int id;
private String poster_path;
private String overview;
private String release_date;
private String original_title;
private String backdrop_path;
private float vote_average;
private Review review;
private Trailer trailer
}
I have Movie class that have two other classes which are Review and Trailer.
Do I have to implements Parcelable to Review and Trailer as well ? or just root class need to implement parcelable ?
I am asking because If I do not have to do my code would be much shorter
Each class you include in your Parcelable must implement Parcelable. You can see an example of how to parcel a Parcelable here
If you want to transfer Movie objects between different Android components, then that should be parcelable and whatever objects inside Movie class are not serializeable/parcelable , you need to make those also parcelable. Otherwise it will not work properly.
Yes you must implement all additional method to make object Parcelable but you can try this library this will make your code simple and will do all job for you

Serializable and Parcelable in Android

I am not clear about distinct use of interface Serializable and Parcelable in Android. If we prefer the use of Parcelable, then why we do so over Serializable. Moreover, if I pass data through any webservice, can Parcelable help? If so, then how?
So the main difference is the speed, and it matters on your hand-held device. Supposedly less powerful than your desktop.
With Serialisable which comes for goold old Java, your code will look like this:
class MyPojo implements Serializable {
String name;
int age;
}
No extra methods are needed as reflection will be used to get all fields and their values. And this can me slow or is slower than ...
and to use Parcelable you have to write something like this:
class MyPojo implements Parcelable {
String name;
int age;
MyPojo(Parcel in) {
name = in.readString();
age = in.readInt();
}
void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
int describeContents() {
return 0;
}
// and here goes CREATOR as well and what not
};
according to guys #google it can be much much faster, Parcelables that is.
Of course, there are tools to help you with adding all necessary fields to make a class Parcelable like https://github.com/johncarl81/parceler

Is it possible to send a custom object with an Intent as an Extra

I'm asking this question: instread of giving a string, a int and so on, can we push a custom object during the creation fo a new Intent?
newActivity.PutExtra("JsonDataResult", business.getJSON());
In fact I have one object constructed thanks to a JSON (from webrequest) , I parse it and I put it on an object.
At this point I'm passing the string returned from the webrequest to another intent but the parsing takes a long time tu be done, so it could be super-cool the ability to pass custom object with intent.
EDIT : I'm using monodroid / xamarin, so
Android.OS.IParcelable cannot be implemented,
Java.IO.ISerializable cannot be implemented.
You can either let your custom classes implement Parcelable (Google says its faster, but you have to do more coding) or Serializable.
Then add your objects to a bundle (or to the "extra"):
Bundle b = new Bundle()
b.putParcelable("myObject",myObject);
b.putSerializable("myObject",myObject);
For info to Parcelablecheckout this
And if you're interested in the difference between Parcelable and Serializable in more detail check out this
I personally prefer the usage of Serializable for simple object-passing, since the code ist not spoiled with so much code.
Edit: ok isn't your question very similar to this then?
As you've specified you're using Monodroid, it looks like it's not straightforward. I did a quick search and found this forum post
Which listed the following solutions to this problem in Monodroid:
Store the custom Object to be passed as a global variable somewhere, and just read it from your second activity
Which is a bit messy and bad practice, but would work.
Or
serialize your class to a string and send the string to the second Activity
Which will be a little more hard work, but better practice
This is an example how to create a Parcelable class:
public class Person implements Parcelable {
private String name;
private String surname;
private String email;
// Get and Set methods
#Override
public int describeContents() {
return hashCode();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(surname);
dest.writeString(email);
}
// We reconstruct the object reading from the Parcel data
public Person(Parcel p) {
name = p.readString();
surname = p.readString();
email = p.readString();
}
public Person() {}
// We need to add a Creator
public static final Parcelable.Creator<person> CREATOR = new Parcelable.Creator<person>() {
#Override
public Person createFromParcel(Parcel parcel) {
return new Person(parcel);
}
#Override
public Person[] newArray(int size) {
return new Person[size];
}
};
Give a look here if you want to use Parcelable.

android pass ArrayList<self_Obj> by Intent

I had create a class named ChannelObj that contains values like this
public class ChannelObj {
public String enable;
public String id;
public String name;
public String ptz;
public ChannelObj(Node n){
this.enable = n.getAttributes().getNamedItem("enabled").getNodeValue();
this.id = n.getAttributes().getNamedItem("id").getNodeValue();
this.name = n.getAttributes().getNamedItem("name").getNodeValue();
this.ptz = n.getAttributes().getNamedItem("ptz").getNodeValue();
}
}
and this Class can create Obj that contains what data I need;
after that,I have an ArrayList named allChannel contains all ChannelObj i have
like this
for(int i = 0;i<num_of_channel;i++)
{
allChannel.add(new ChannelObj(n1.item(i)));
}
i've checked the data in allChannel is correct
but i want pass this ArrayList to next Activity
i've tried ways like
Intent i = new Intent(this,ChannelListActivity.class);
Bundle b = new Bundle();
b.putParcelableArrayListExtra("dd", ArrayList<ChannelObj> allChannels);
i.putExtra(String name,b);
startActivity(i);
but didn't work and still wrong
what i suppose to do?
thanks for your help!
An alternative to the answer given by Benoir is to have your ChannelObj class implement the Serializable interface. You're only using simple data types, so all the (de)serializing will be automa(g)(t)ically done underwater.
If your class implements Serializable, then you can add it to a Bundle as follows:
bundle.putSerializable("CHANNELOBJ_LIST", mChannelObjList);
Note that you may need to cast to an ArrayList<ChannelObj> (or some other concrete implementation of List<T>) as the List<T> interface does not implement Serializable.
Retrieving the list of objects in the next activity is similarly easy:
List<ChannelObj> mChannelObjList = (ArrayList<ChannelObj>) bundle.getSerializable("CHANNELOBJ_LIST");
Your clas must implement Parcelable check it out here: http://developer.android.com/reference/android/os/Parcelable.html

Categories

Resources