Parcelable工作原理

一、Parcelable的作用

Parcelable是Android为我们提供的序列化接口。

什么是序列化呢?简单说就是将对象转换为可以传输的二进制流(二进制序列)的过程,这样我们就可以通过序列化,转化为可以在网络传输或者保存到本地的流(序列),从而进行数据传输,反序列化就是从二进制流(序列)转换为对象的过程。

为什么要序列化呢?

1)永久性保存对象,保存对象的字节序列到本地文件中;

2)通过序列化对象在网络中传递对象;

3)通过序列化在进程间传递对象。

 

二、Parcelable和Serializable的比较

Parcelable的性能比Serializable好,因为Serializable在反射过程中会频繁GC。所以在内存间数据传输时推荐使用Pacelable,如Activity间的数据传输;Serializable可将数据持久化方便保存,Parcelable在不同android版本可能不同,而且在外界有变化的情况下不能很好的保证数据的持续性,所以在需要保存或网络传输数据时选择Serializable。

 

三、Parcelable的使用

1、implements Parcelable接口

2、重写writeToParcel()方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中

3、重写describeContents()方法,内容接口描述方法,默认返回0即可,只针对一些特殊的需要描述信息的对象需要返回1。

4、实例化静态内部对象CREATOR实现接口Parcelable.Creator,public static final Parcelable.Creator<T> CREATOR

其中public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写。需要重写Creator接口中的两个方法:

T createFromParcel(Parcel in):实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层。

T[] newArray(int size):创建一个类型为T、长度为size的数组,供外部类反序列化本类数组使用。

 

简而言之就是通过writeToParcel()方法将你的对象映射成Parcel对象,再通过createFromParcel()方法将Parcel对象映射成你的对象,也可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,再通过createFromParcel从流里读取对象,只不过这个读写过程需要你自己来实现,所以写的顺序和读的顺序必须一致。

 

四、Parcelable传递复杂对象

private byte byteData;
private short shortData;
private int intData;
private long longData;
private float floatData;
private double doubleData;
private char charData;
private boolean booleanData;
private String stringData;
private BigDecimal bigDecimalData;
private OuterEntity outerEntity;
private List<OuterEntity> outerList;
private InnerEntity innerEntity;
private List<InnerEntity> innerList;
private Map<String, OuterEntity> map1;
private Map<Integer, List<OuterEntity>> map2;

Parcelable要将如上定义的数据类型序列化,其中bigDecimalData、map1、map2三个属性序列化的时候是不做处理的,需要自己手动增加一下。

1)writeToParcel()方法:

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeByte(byteData);
    dest.writeInt((int) shortData);
    dest.writeInt(intData);
    dest.writeLong(longData);
    dest.writeFloat(floatData);
    dest.writeDouble(doubleData);
    dest.writeInt((int) charData);
    dest.writeByte((byte) (booleanData ? 1 : 0));
    dest.writeString(stringData);
    dest.writeString(bigDecimalData == null ? "0" : bigDecimalData.toString());
    dest.writeParcelable(outerEntity, flags);
    dest.writeTypedList(outerList);
    dest.writeParcelable(innerEntity, flags);
    dest.writeTypedList(innerList);
    if (null != map1 && map1.size() > 0) {
        dest.writeInt(map1.size());//先写入map的大小
        for (Map.Entry<String, OuterEntity> entry : map1.entrySet()) {
            dest.writeString(entry.getKey());
            dest.writeParcelable(entry.getValue(), flags);
        }
    }
    if (null != map2 && map2.size() > 0) {
        dest.writeInt(map2.size());
        for (Map.Entry<Integer, List<OuterEntity>> entry : map2.entrySet()) {
            dest.writeInt(entry.getKey());
            dest.writeTypedList(entry.getValue());
        }
    }
}

2)读出方法:

protected ParcelableEntity(Parcel in) {
    byteData = in.readByte();
    shortData = (short) in.readInt();
    intData = in.readInt();
    longData = in.readLong();
    floatData = in.readFloat();
    doubleData = in.readDouble();
    charData = (char) in.readInt();
    booleanData = in.readByte() != 0;
    stringData = in.readString();
    bigDecimalData=new BigDecimal(in.readString());
    outerEntity = in.readParcelable(OuterEntity.class.getClassLoader());
    outerList = in.createTypedArrayList(OuterEntity.CREATOR);
    innerEntity = in.readParcelable(InnerEntity.class.getClassLoader());
    innerList = in.createTypedArrayList(InnerEntity.CREATOR);
    if (map1 == null) map1 = new HashMap<>();
    int map1Size = in.readInt();
    if (map1Size > 0) {
        for (int i = 0; i < map1Size; i++) {
            String key = in.readString();
            OuterEntity value = in.readParcelable(OuterEntity.class.getClassLoader());
            map1.put(key, value);
        }
    }
    if (map2 == null) map2 = new HashMap<>();
    int map2Size = in.readInt();
    if (map2Size > 0) {
        for (int i = 0; i < map2Size; i++) {
            Integer key = in.readInt();
            List<OuterEntity> value = in.createTypedArrayList(OuterEntity.CREATOR);
            map2.put(key, value);
        }
    }
}

五、有继承关系的实体序列化

Parcelable序列化需要在最自层的实体类中实现Parcelable接口,并在最自层的实体类中把父类所有的属性都序列化;Serializable只需在最外层的父类实体类中实现Serializable接口。

protected ParcelableSubclassEntity(Parcel in) {
    parentAge=in.readInt();
    parentName=in.readString();
    subclassAge = in.readInt();
    subclassName = in.readString();
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(parentAge);
    dest.writeString(parentName);
    dest.writeInt(subclassAge);
    dest.writeString(subclassName);
}

完整代码:https://github.com/ruxing1102/SerializationPractice/tree/master

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值