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, the Parcelable interface allows your classes to be flattened inside a message container called a Parcel to 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:

  1. public class Conversation implements Parcelable {  
  2.   
  3.     // ...  
  4.     protected String lastComment;  
  5.     protected Integer messageCount;  
  6.     protected Date createdAt;  
  7.     // ...  
  8.   
  9.     // ...  
  10.     public Conversation(Parcel in) {  
  11.      readFromParcel(in);  
  12.     }  
  13.   
  14.     @Override  
  15.     public void writeToParcel(Parcel out, int flags) {  
  16.         // ...  
  17.         out.writeString(lastComment);  
  18.         out.writeInt(messageCount);  
  19.  out.writeSerializable(createdAt);  
  20.         // ...  
  21.     }  
  22.   
  23.     private void readFromParcel(Parcel in) {    
  24.         // ...  
  25.         lastComment = in.readString();  
  26.  messageCount = in.readInt();  
  27.  createdAt = (Date) in.readSerializable();  
  28.         // ...  
  29.     }  
  30.   
  31.     public static final Parcelable.Creator<conversation> CREATOR = new Parcelable.Creator<conversation>() {  
  32.     
  33.         public Conversation createFromParcel(Parcel in) {  
  34.             return new Conversation(in);  
  35.         }  
  36.    
  37.         public Conversation[] newArray(int size) {  
  38.             return new Conversation[size];  
  39.         }  
  40.           
  41.     };  
  42.   
  43.     @Override  
  44.     public int describeContents() {  
  45.         return 0;  
  46.     }  
  47.   
  48. }  
  49. </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 the fromUser property holds a User instance, then writing the user data to parcel would be accomplished as shown below:

  1. @Override  
  2. public void writeToParcel(Parcel out, int flags) {  
  3.     // ...  
  4.     out.writeParcelable(fromUser, flags);  
  5.     // ...  
  6. }  

Reading the user data from parcel:

  1. private void readFromParcel(Parcel in) {    
  2.     // ...  
  3.     fromUser = in.readParcelable(User.class.getClassLoader());  
  4.     // ...  
  5. }  

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:

  1. @Override  
  2. public void writeToParcel(Parcel out, int flags) {  
  3.     // ...  
  4.     out.writeList(messages);  
  5.     // ...  
  6. }  

Reading from the parcel:

  1. private void readFromParcel(Parcel in) {    
  2.     // ...  
  3.     in.readList(messages, Message.class.getClassLoader());  
  4.     // ...  
  5. }  

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:

  1. @Override  
  2. public void writeToParcel(Parcel out, int flags) {  
  3.     // ...  
  4.     out.writeInt(booleanValue ? 1 : 0);  
  5.     // ...  
  6. }  

Reading from the parcel:

  1. private void readFromParcel(Parcel in) {    
  2.     // ...  
  3.     booleanValue = in.readInt() == 1;  
  4.     // ...  
  5. }  

ENUM TYPES

To flatten an Enum type in a parcel, simply implement the Parcelable interface for the Enum type. Here is an example:

  1. public enum Status implements Parcelable {  
  2.     
  3.     STARTED, PAUSED, FINISHED;  
  4.     
  5.     public static final Parcelable.Creator<status> CREATOR = new Parcelable.Creator<status>() {  
  6.      
  7.         public Status createFromParcel(Parcel in) {  
  8.             return Status.values()[in.readInt()];  
  9.  }  
  10.    
  11.         public Status[] newArray(int size) {  
  12.      return new Status[size];  
  13.  }  
  14.            
  15.     };  
  16.   
  17.     @Override  
  18.     public int describeContents() {  
  19.  return 0;  
  20.     }  
  21.   
  22.     @Override  
  23.     public void writeToParcel(Parcel out, int flags) {  
  24.  out.writeInt(ordinal());  
  25.     }  
  26.   
  27. }  
  28. </status></status>  

When writing to the parcel, treat it as a nested Parcelable class:

  1. @Override  
  2. public void writeToParcel(Parcel out, int flags) {  
  3.     // ...  
  4.     out.writeParcelable(status, flags);  
  5.     // ...  
  6. }  

Reading from the parcel:

  1. private void readFromParcel(Parcel in) {    
  2.     // ...  
  3.     status = in.readParcelable(Status.class.getClassLoader());  
  4.     // ...  
  5. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值