Serializable and Parcelable in Android - 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

Related

Android Parcelable: reading and writing

I want to make a custom entity class Parcelable.. I have some fields in it: a String[] and another custom entity object (which is parcelable).. I want to know how to read and write these objects and lists..
public class CustomEntity implements Parcelable {
private int number;
private String[] urls;
private AnotherEntity object;
public CustomEntity(Parcel in) {
number = in.readInt();
// how should I read urls?
// how should I read object?
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(number);
// how should I write urls?
// how should I write object?
}
}
For a String[] you can use the API
parcel.writeStringArray(url)
For AnotherEntity you need to extend it with Parcelable again
parcel.writeParcelable();
https://github.com/mcharmas/android-parcelable-intellij-plugin use this plugin!
Your AnotherEntity must implemented Parcelable too!
I definitely think you should NOT handle the boilerplate yourself.
There are libraries around like Parceler where with only one annotation on your POJO and one line like Parcel.wrap or Parcel.unwrap you can do instant serialization.

Is it possible to a List of Objects in putExtra

I know putExtra can be used to pass objects/strings around between actives. But I am trying you put an ArrayList of objects like ArrayList<Foo> in putExtra
Is this possible?
No it isn't. You'll need to serialize your object into some kind of string representation. One possible string representation is JSON, and one of the easiest ways to serialize to/from JSON in android, if you ask me, is through Google GSON.
Also if you're just passing objects around then Parcelable was designed for this. It requires a little more effort to use than using Java's native serialization, but it's way faster (and I mean way, WAY faster).
From Docs :
public class MyParcelable implements Parcelable {
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
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();
}
}
You can use
intent.putParcelableArrayListExtra() for passing Arraylist in intent.
Refer to http://developer.android.com/reference/android/content/Intent.html#putParcelableArrayListExtra(java.lang.String, java.util.ArrayList)
EDIT :
one more link : Help with passing ArrayList and parcelable Activity
Only for very limited and particular types of "Foo". If i recall correctly Double and Long (or maybe it was Integer?) being those types. There might be a way to smuggle a more generic ArrayList through by encapsulating it in some Serializable Object, but I'm not sure about that.

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 Parcelable and Serializable

So i know it is recommended to use Parcelable instead of Serializable in android, because it is faster.
My question is: is that impossible to avoid using Serializable right?
If I have a custom object i want to serialize, let's say I have the following class definition
public class Person {
String name;
int Age;
...
....
}
Making this parcelable is easy, because the Person class contains the types parcel.write*() supports, i.e. there is parcel.writeString and parcel.writeInt
Now, what if the Person class is the following:
public class PersonTwo {
MyCustomObj customObj;
String name;
int Age;
...
....
}
How am I suppose to parcel the MyCustomObj object??
It seems I need to use serializable again? but again, I thought it is SLOW to use serializable, and seems we have no choice but to use it in this case.
I don't understand
can someone tell me how I would parcel PersonTwo in this case?
The link given by Ajay is the exact what you are looking for, how you can do it.
Well, what you can do is implement Parcelable to your CustomObject1 and create a Parcelable class for it and then you can use that Parcelable class to Parcel it inside another Parcelable class that will Parcel both the CustomObjects.
public class CustomObject1 implements Parcelable {
// parcelable code CustomObject1
}
public class CustomObject2 implements Parcelable {
private CustomObject1 obj1;
// add CustomObject1 here with getter setter
// parcelable code for CustomObject2
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(obj1, flags);
}
private void readFromParcel(Parcel in) {
obj1 = in.readParcelable(CustomObject1.class.getClassLoader());
}
............
}
You need to make MyCustomObj parcelable.
All the composite objects should also be Parcelable. In case, you want to skip an object then don't use it writeToParcel method.
I came to point where Parcelable is an issue for me.
On Android 4.3, I am getting unmarhalling exception, when passing data between
Activities as Parcelable. It works OK on Android 4.0, 4.2 or 4.4.
It should work when changed to Serializable, even though, it is slower.

android nested object parceling

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.

Categories

Resources