IPC通信基础介绍之Serializable和Parcelable详解

IPC通信基础介绍之Serializable和Parcelable详解

都是用来序列化的,什么时候用到序列化呢?

1、把对象持久化到存储设备上,保存对象的字节序列到本地文件中。

2、通过网络传输给其他客户端。

3、通过Intent和Binder传输数据。


Serializable接口

  serializable是java提供的一个序列化接口,它是一个空接口,使用特别简单,只需要实现Serializable接口即可。

  在实现Serializable接口的同时,会有一个可有可无的serialVersionUID参数,这个参数可有可无是因为它对我们正常序列化是没有影响的,它只对反序列化产生影响,稍后说明对反序列化的影响。

private static final long serialVersionUID = 871136744783885433L
  通过Serializable实现的序列化,几乎所有的工作都被系统自动完成了。

public class User implements Serializable {

    private static final long serialVersionUID = 519067123721295773L;
    private int userId;
    private String name;
    private boolean isMale;

}
  针对序列化和反序列化过程其实可以通过ObjectOutputStream和ObjectInputStream实现。

 //序列化过程
        User user = new User(0, true, "aaa");
        try {
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.txt"));
            out.writeObject(user);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //反序列化过程
        try {
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.txt"));
            User newUser = (User) in.readObject();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
  反序列化后的对象newUser和user的内容完全一样,但是他们并不是同一个对象。

  对于参数serialVersionUID,它既可以手动指定,也可以系统自动生成。它的工作机制是这样的,在当前类进行序列化的过程中serialVersionUID会被写入序列化文件中,当这个类进行反序列化的时候系统会去检测文件中的serialVersionUID和当前类中的是否一致,如果一致说明当时被序列化的类的版本和当前类的版本是相同的,那么就可以成功实现反序列化;如果不一致,就说明当前类发生了变化,例如成员变量数量、类型等发生了改变,这个时候反序列化就会失败。

  对于serialVersionUID的手动生成和系统自动生成区别在于,如果类中的成员变量在数量和类型上发生了改变,那么手动生成的serialVersionUID不会改变,也就不会反序列化失败;反之,系统是根据类的结构自动生成的hash值,如果成员变量发生了改变,那么对应的hash值也会发生改变,就会造成当前成员变量已经发生改变的类的serialVersionUID和之前序列化保存在文件中的serialVersionUID对应不起来,从而反序列化失败。

  注意:静态的成员变量属于类不属于对象,所以不会参与序列化过程;还有是transient关键字标记的成员变量不参与序列化过程。


Parcelable接口

  Parcelable是Android提供的一个接口,实现这个接口就可以实现序列化对象。

一个实现Parcelable的子类Child:

public class Child implements Parcelable {
    public String id;
    public String name;
    public boolean isMale;

    protected Child(Parcel in) {
        id = in.readString();
        name = in.readString();
        isMale = in.readByte() != 0;
    }

    public static final Creator<Child> CREATOR = new Creator<Child>() {
        @Override
        public Child createFromParcel(Parcel in) {
            return new Child(in);
        }

        @Override
        public Child[] newArray(int size) {
            return new Child[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(id);
        dest.writeString(name);
        dest.writeByte((byte) (isMale ? 1 : 0));
    }
}

一个含有Child的成员变量的父类Parent:

public class Parent implements Parcelable {

    public String id;
    public String name;
    public boolean isMale;
    public Child child;


    /**
     * 实现反序列化功能,通过一系列read方法完成
     *
     * @param in
     */
    protected Parent(Parcel in) {
        id = in.readString();
        name = in.readString();
        isMale = in.readByte() != 0;
        child = in.readParcelable(Child.class.getClassLoader());
    }

    /**
     * 完成反序列化
     */
    public static final Creator<Parent> CREATOR = new Creator<Parent>() {
        /**
         * 从序列化后的对象中创建原始对象
         * @param in
         * @return
         */
        @Override
        public Parent createFromParcel(Parcel in) {
            return new Parent(in);
        }

        /**
         * 创建指定长度的原始对象数组
         * @param size
         * @return
         */
        @Override
        public Parent[] newArray(int size) {
            return new Parent[size];
        }
    };

    /**
     * 内容描述功能
     * 含有文件描述返回1,否则返回0,几乎所有情况都返回0
     *
     * @return
     */
    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * 将当前对象写入序列化结构中
     * 是通过一些列的wtire方法完成的
     *
     * @param dest
     * @param flags
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(id);
        dest.writeString(name);
        dest.writeByte((byte) (isMale ? 1 : 0));
        dest.writeParcelable(child, flags);
    }
}

在以上代码中序列化功能由wtireToParcel方法完成,反序列化是由CREATOR完成。在Parent中的成员变量Child,Child也必须是实现Parcelable可序列化的。


  对于实现序列化对于两则的选取是各有优缺点的。Serializable是java中的序列化接口,其序列化过程需要大量的I/O操作,性能消耗比较大。而Parcelable是Android中提供的,因此可能更加适合在安卓开发中使用,它的缺点就是使用比较麻烦,但是效率比较高。至于选择哪个个人感觉还是看实际项目复杂情况吧。





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值