A Parcelable Tutorial for Android
PARCELABLE INTERFACE OVERVIEW
In one of my earlier posts, I mentioned writing an article about FOSOAuthBundle integration with an Android client. To keep that article to the point, I need to explain some concepts beforehand. One of the important concepts is the Android Parcelable interface that allows data to be transferred between different processes/threads. Certain network operations with Android such as authentication with OAuth2 and then fetching data from a REST endpoint should be performed in the background in order not to block the UI thread. This requires data to be fetched by a service (I have opted for Intent Services in my implementation) in the background and then passed back to the calling activity/fragment with a result callback. This is where the Parcelable interface comes into play.
Basically, theParcelableinterface allows your classes to be flattened inside a message container called aParcelto facilitate high performance inter process communication. The received parcel data can then be unflattened to generate object/entity instances.
A BASIC PARCELABLE EXAMPLE
A Parcelable implementation is pretty straight forward. Override the necessary methods called writeToParcel() and describeContents(), add a static field called CREATOR which generates instances of your Parcelable class from a Parcel, and overload the class constructor which expects a Parcel as a parameter and calls the readFromParcel() utility method. Here is a basic example:
view plain print ?- publicclassConversationimplementsParcelable{
- //...
- protectedStringlastComment;
- protectedIntegermessageCount;
- protectedDatecreatedAt;
- //...
- //...
- publicConversation(Parcelin){
- readFromParcel(in);
- }
- @Override
- publicvoidwriteToParcel(Parcelout,intflags){
- //...
- out.writeString(lastComment);
- out.writeInt(messageCount);
- out.writeSerializable(createdAt);
- //...
- }
- privatevoidreadFromParcel(Parcelin){
- //...
- lastComment=in.readString();
- messageCount=in.readInt();
- createdAt=(Date)in.readSerializable();
- //...
- }
- publicstaticfinalParcelable.Creator<conversation>CREATOR=newParcelable.Creator<conversation>(){
- publicConversationcreateFromParcel(Parcelin){
- returnnewConversation(in);
- }
- publicConversation[]newArray(intsize){
- returnnewConversation[size];
- }
- };
- @Override
- publicintdescribeContents(){
- return0;
- }
- }
- </conversation></conversation>
NESTED PARCELABLE CLASSES
Lets say we have a Conversation class instance with an embedded User class instance that holds some information about a user that has initiated the conversation. Basically, we are talking about an one-to-one embedded mapping. In this case, if thefromUserproperty holds a User instance, then writing the user data to parcel would be accomplished as shown below:
view plain print ?- @Override
- publicvoidwriteToParcel(Parcelout,intflags){
- //...
- out.writeParcelable(fromUser,flags);
- //...
- }
Reading the user data from parcel:
view plain print ?- privatevoidreadFromParcel(Parcelin){
- //...
- fromUser=in.readParcelable(User.class.getClassLoader());
- //...
- }
If you have a one-to-many embedded relationship such as a list of messages in a conversation, then the syntax would change as follows:
view plain print ?- @Override
- publicvoidwriteToParcel(Parcelout,intflags){
- //...
- out.writeList(messages);
- //...
- }
Reading from the parcel:
view plain print ?- privatevoidreadFromParcel(Parcelin){
- //...
- in.readList(messages,Message.class.getClassLoader());
- //...
- }
BOOLEAN TYPES
Android API does not have a method to write a single boolean value to a parcel. In this case, you can utilize the writeInt() method as shown below:
view plain print ?- @Override
- publicvoidwriteToParcel(Parcelout,intflags){
- //...
- out.writeInt(booleanValue?1:0);
- //...
- }
Reading from the parcel:
view plain print ?- privatevoidreadFromParcel(Parcelin){
- //...
- booleanValue=in.readInt()==1;
- //...
- }
ENUM TYPES
To flatten an Enum type in a parcel, simply implement the Parcelable interface for the Enum type. Here is an example:
view plain print ?- publicenumStatusimplementsParcelable{
- STARTED,PAUSED,FINISHED;
- publicstaticfinalParcelable.Creator<status>CREATOR=newParcelable.Creator<status>(){
- publicStatuscreateFromParcel(Parcelin){
- returnStatus.values()[in.readInt()];
- }
- publicStatus[]newArray(intsize){
- returnnewStatus[size];
- }
- };
- @Override
- publicintdescribeContents(){
- return0;
- }
- @Override
- publicvoidwriteToParcel(Parcelout,intflags){
- out.writeInt(ordinal());
- }
- }
- </status></status>
When writing to the parcel, treat it as a nested Parcelable class:
view plain print ?- @Override
- publicvoidwriteToParcel(Parcelout,intflags){
- //...
- out.writeParcelable(status,flags);
- //...
- }
Reading from the parcel:
view plain print ?- privatevoidreadFromParcel(Parcelin){
- //...
- status=in.readParcelable(Status.class.getClassLoader());
- //...
- }
更多相关文章
- 代码中设置drawableleft
- android 3.0 隐藏 系统标题栏
- Android开发中activity切换动画的实现
- Android(安卓)学习 笔记_05. 文件下载
- Android中直播视频技术探究之—摄像头Camera视频源数据采集解析
- 技术博客汇总
- android 2.3 wifi (一)
- AndRoid Notification的清空和修改
- Android中的Chronometer