[原创]如何在Parcelable中使用泛型
实体类在实现Parcelable接口时,除了要实现它的几个方法之外,还另外要定义一个静态常量CREATOR,如下例所示:
1 public static class ProductModel implements Parcelable { 2 public String id; 3 public String title; 4 public String sold_num; 5 public String max_month; 6 public String cprice; 7 public double month_price; 8 public List<String> gpic; 9 10 @Override 11 public int describeContents() { 12 return 0; 13 } 14 15 @Override 16 public void writeToParcel(Parcel dest, int flags) { 17 dest.writeString(this.id); 18 dest.writeString(this.title); 19 dest.writeString(this.sold_num); 20 dest.writeString(this.max_month); 21 dest.writeString(this.cprice); 22 dest.writeDouble(this.month_price); 23 dest.writeStringList(this.gpic); 24 } 25 26 public ProductModel() { 27 } 28 29 protected ProductModel(Parcel in) { 30 this.id = in.readString(); 31 this.title = in.readString(); 32 this.sold_num = in.readString(); 33 this.max_month = in.readString(); 34 this.cprice = in.readString(); 35 this.month_price = in.readDouble(); 36 this.gpic = in.createStringArrayList(); 37 } 38 39 public static final Creator<ProductModel> CREATOR = new Creator<ProductModel>() { 40 public ProductModel createFromParcel(Parcel source) { 41 return new ProductModel(source); 42 } 43 44 public ProductModel[] newArray(int size) { 45 return new ProductModel[size]; 46 } 47 };
CREATOR在这里成为了一个约定,而没有放到接口定义里面,个人感觉这样封装得不是很好,不知道是不是实在没有更好的解决办法才弄成这样的?
假如在类里要使用泛型,麻烦就来了,例如这样
1 public class PageDataModel<T extends Parcelable> extends APIDataModel { 2 3 static final String DATA_KEY = "data"; 4 5 /** 6 * count : 1 7 * total_pages : 1 8 * list_rows : 10 9 * first_row : 0 10 */ 11 12 public int count; 13 public ArrayList<T> data; 14 public int total_pages; 15 public int list_rows; 16 public int first_row; 17 }
这个data,就无法正常read(write倒是可以)。
正常的write方式是这样的:
this.data = dest.createTypedArrayList(Parcelable.Creator<T> c)
那么问题来了,你只有一个泛型T,没有具体类型,拿不到它的CREATOR!CREATOR只是一个约定,而且是跟具体类型绑定的。
所以我前面说如果这个CREATOR能通过某种方式定义下来,这里或许就能拿到了,然而并没有。
但是android系统你是改变不了的,我们仍然要解决问题。经过多番调查尝试之后,终于找到了解决办法:
Pacel是可以读取和写入Bundle对象的,而Bundle对象又可以读取和写入Parcelable,而且不需要CREATOR(为啥Parcel不能设计成这样,坑爹呢。。)
那么 我们把泛型数据用Bundle包装一下即可,下面是具体代码,亲测有效,总算解决这个问题了。
1 //write 2 Bundle bundle = new Bundle(); 3 bundle.putParcelableArrayList(DATA_KEY, data); 4 dest.writeBundle(bundle); 5 6 //read 7 this.data = in.readBundle().getParcelableArrayList(DATA_KEY);