Android - Parcel data to pass between Activities using Parcelable classes
Passing data between activities on android is unfortunately, not as simple as
passing in parameters. What we need to to do is tag these onto the intent. If
the information we need to pass across is a simple object like a String or
Integer, this is easy enough.
Passing in custom objects is a little more complicated. You could just mark the
class
as Serializable
and let Java take care of this. However, on the android, there is a serious
performance hit that comes with using Serializable. The solution is to
use Parcelable
.
packageuk.co.kraya.android.demos.Parcelable;importandroid.os.Parcel;importandroid.os.Parcelable;/**
* @author Shriram Shri Shrikumar
*
* A basic object that can be parcelled to
* transfer between objects
*
*/publicclassObjectAimplementsParcelable{privateStringstrValue;privateIntegerintValue;/**
* Standard basic constructor for non-parcel
* object creation
*/publicObjectA(){;};/**
*
* Constructor to use when re-constructing object
* from a parcel
*
* @param in a parcel from which to read this object
*/publicObjectA(Parcelin){readFromParcel(in);}/**
* standard getter
*
* @return strValue
*/publicStringgetStrValue(){returnstrValue;}/**
* Standard setter
*
* @param strValue
*/publicvoidsetStrValue(StringstrValue){this.strValue=strValue;}/**
* standard getter
*
* @return
*/publicIntegergetIntValue(){returnintValue;}/**
* Standard setter
*
* @param intValue
*/publicvoidsetIntValue(IntegerintValue){this.intValue=intValue;}@OverridepublicintdescribeContents(){return0;}@OverridepublicvoidwriteToParcel(Parceldest,intflags){// We just need to write each field into the// parcel. When we read from parcel, they// will come back in the same orderdest.writeString(strValue);dest.writeInt(intValue);}/**
*
* Called from the constructor to create this
* object from a parcel.
*
* @param in parcel from which to re-create object
*/privatevoidreadFromParcel(Parcelin){// We just need to read back each// field in the order that it was// written to the parcelstrValue=in.readString();intValue=in.readInt();}/**
*
* This field is needed for Android to be able to
* create new objects, individually or as arrays.
*
* This also means that you can use use the default
* constructor to create the object and use another
* method to hyrdate it as necessary.
*
* I just find it easier to use the constructor.
* It makes sense for the way my brain thinks ;-)
*
*/publicstaticfinalParcelable.CreatorCREATOR=newParcelable.Creator(){publicObjectAcreateFromParcel(Parcelin){returnnewObjectA(in);}publicObjectA[]newArray(intsize){returnnewObjectA[size];}};}
The intricacies of the class is described in the code above. There is now one
more special case. What if you have an object that references another object.
Clearly, they would both need to be Parcelable, but how would be integrate them.
ObjectB shows a parcelable embedded in another parcelable…
packageuk.co.kraya.android.demos.Parcelable;importandroid.os.Parcel;importandroid.os.Parcelable;publicclassObjectBimplementsParcelable{privateObjectAobj;privateLonglongVal;publicObjectB(){;}publicObjectAgetObj(){returnobj;}/**
*
* Constructor to use when re-constructing object
* from a parcel
*
* @param in a parcel from which to read this object
*/publicObjectB(Parcelin){readFromParcel(in);}publicvoidsetObj(ObjectAobj){this.obj=obj;}publicLonggetLongVal(){returnlongVal;}publicvoidsetLongVal(LonglongVal){this.longVal=longVal;}@OverridepublicintdescribeContents(){return0;}@OverridepublicvoidwriteToParcel(Parceldest,intflags){// The writeParcel method needs the flag// as well - but thats easy.dest.writeParcelable(obj,flags);// Same as in ObjectAdest.writeLong(longVal);}/**
*
* Called from the constructor to create this
* object from a parcel.
*
* @param in parcel from which to re-create object
*/privatevoidreadFromParcel(Parcelin){// readParcelable needs the ClassLoader// but that can be picked up from the class// This will solve the BadParcelableException// because of ClassNotFoundExceptionobj=in.readParcelable(ObjectA.class.getClassLoader());// The rest is the same as in ObjectAlongVal=in.readLong();}/**
*
* This field is needed for Android to be able to
* create new objects, individually or as arrays.
*
* This also means that you can use use the default
* constructor to create the object and use another
* method to hyrdate it as necessary.
*
* I just find it easier to use the constructor.
* It makes sense for the way my brain thinks ;-)
*
*/publicstaticfinalParcelable.CreatorCREATOR=newParcelable.Creator(){publicObjectBcreateFromParcel(Parcelin){returnnewObjectB(in);}publicObjectB[]newArray(intsize){returnnewObjectB[size];}};}
When writing the parcel, we need to pass in the flags - which is easy enough.
When reading the parcel, we need the classloader, which can be picked up from
destination class of the parcelable. Again easy!
Finally, passing a parcelable object to an intent
1
2
3
4
5
6
7
8
ObjectAobj=newObjectA();// Set values etc.Intenti=newIntent(this,MyActivity.class);i.putExtra("com.package.ObjectA",obj);startActivity(i);