Few days back I had a requirement to send ArrayList of my Custom Class/Objects which need to be sent through Intent, I guess most of you also find this requirement now and then. I never thought it can be that tricky.
There are built in functions in Intent to send ArrayList of primitive objects e.g. String, Integer, but when it comes to Custom Data Handling Objects, BOOM… you need to take that extra pain…..
Android has defined a new light weight IPC (Inter Process Communication) data structure called Parcel, where you can flatten your objects in byte stream, same as J2SDK’s Serialization concept.
So let’s come back to my original requirement, I had a Data Handling class, which groups together a set of information-
public
class
ParcelData
{
int
id
;
String
name
;
String
desc
;
String[]
cities
= {
"suwon"
,
"delhi"
};
}
I want an ArrayList<ParcelData > of Data Handling objects to be able to pass through Intent. To do that, I can’t use the ParcelData as it is; you need to implement an Interface
android.os.Parcelable
which will make Objects of this class Parcelable. So you need to define your data handling class as-
public
class
ParcelData
implements
Parcelable
{
int
id
;
String
name
;
String
desc
;
String[]
cities
= {
"suwon"
,
"delhi"
};
}
You need to overwrite2 methods of
android.os.Parcelable
Interface-
describeContents()
-
define the kind of object you are going to Parcel, you can use the hashCode() here.
writeToParcel(Parcel dest, int flags)
-
actual object serialization/flattening happens here. You need to individually Parcel each element of the object.
public
void
writeToParcel(Parcel dest,
int
flags) {
Log.v (
TAG
,
"writeToParcel..."
+ flags);
dest.writeInt(
id
);
dest.writeString(
name
);
dest.writeString(
desc
);
dest.writeStringArray(
cities
);
}
Note:
Don’t try things like,
dest
.writeValue(this)
to flatten the complete Object at a time (I don’t think all people have some weird imaginations like me, so you’ll never try this, right ?…) that will end up in recursive call of
writeToParcel()
.
Up to this point you are done with the required steps to flatten/serialize your custom object.
Next, you need to add steps to un-marshal/un-flatten/de-serialize (whatever you call it) your custom data objects from Parcel. You need to define one weird variable called
CREATOR
of type
Parcelable.Creator
. If you don’t do that, Android framework will through exception-
Parcelable
protocol requires a Parcelable .Creator object called CREATOR
Following is a sample implementation of
Parcelable.Creator
<
ParcelData
>
interface for my class
ParcelData.java
-
/**
*
It
will
be
required
during
un
-
marshaling
data
stored
in
a
Parcel
*
@author
prasanta
*/
public
class
MyCreator
implements
Parcelable.Creator
<
ParcelData
> {
public
ParcelData createFromParcel(Parcel source) {
return
new
ParcelData(source);
}
public
ParcelData[] newArray(
int
size) {
return
new
ParcelData[size];
}
}
You need to define a Constructor in
ParcelData.java
which puts together all parceled data back-
/**
*
This
will
be
used
only
by
the
MyCreator
*
@param
source
*/
public
ParcelData
(Parcel source)
{
/*
* Reconstruct from the Parcel
*/
Log.v (
TAG
,
"ParcelData(Parcel source): time to put back parcel data"
);
id
= source.readInt();
name
= source.readString();
desc
= source.readString();
source.readStringArray(
cities
);
}
You can deserve some rest now…...as you are done with it.
So now you can use, something like-
Intent
parcelIntent =
new
Intent
(
this
,
ParcelActivity
.
class
);
ArrayList
<
ParcelData
> dataList =
new
ArrayList
<
ParcelData
>();
/*
* Add elements in dataLists e.g.
* ParcelData pd1 = new ParcelData();
* ParcelData pd2 = new ParcelData();
*
* fill in data in pd1 and pd2
*
* dataLists.add(pd1);
* dataLists.add(pd2);
*/
parcelIntent.putParcelableArrayListExtra(
"custom_data_list"
, data);
So, how hard is that?
:-)