android 支持的序列化-------Serializable和Parcelble

来源:互联网 发布:ubuntu 安装 uefi启动 编辑:程序博客网 时间:2024/06/14 06:52

android 支持两种序列化:Serializable和Parcelble。前者是Java语言自带的序列化机制,通过读写文件实现对象的序列化和反序列化;后者是Android Os实现的序列化,它是通过读写内存来实现序列化,从而实现对象的传递。下面,就这两种方式详细说明。

Serializable

Serializable是Java提供的一个空接口。对象要想实现序列化,只需要如下:

public class SerializableClass implements Serializable{    private static final long serialVersionUID = 1L;    ......}

继承自Serializable,并且提供一个serialVersionUID即可。然后 通过对象输出流就可以实现序列化,通过对象输入流就可以实现反序列化。但是,需要注意的是:

  1. 静态成员不输入单个对象,不参与序列化;
  2. 使用transient关键字修饰的成员不参与序列化。

serialVersionUID用来在反序列化的时候做校验。反序列化时,会检测文件中的serialVersionUID和类的serialVersionUID是否一致,如果一致,则说明可以进行序列化,否则说明类的版本不匹配,不能进行序列化。

如果不指定serialVersionUID,在进行序列化的时候,会默认根据当前类的结构,生成hash值作为serialVersionUID写到文件,在反序列化的时候,同样会生成类的hash值并和文件中序列化写入的serialVersionUID进行比较,如果一致就可以序列化,否则不可以。这样会造成一个问题:如果序列化之后,类有了修改,那么,此时默认生成的hash值和之前序列化写入的hash值不匹配,导致无法序列化。

为了克服这个问题,最好手动指定serialVersionUID,或者由IDE工具自动生成。这样的好处是,及时序列化后,类做了小的改动,比如增加或删除了成员变量,那么,还是可以反序列恢复对象。但是,如果类的结构发生了非常规的改变,则无法反序列化,比如,修改了类名等。

Parcelable

Parcelable同样也是一个接口。它主要完成序列化和反序列化以及内容描述功能。User是一个Parcelable类:

public class User implements Parcelable{    public int userId;    public String userName;    public boolean isMale;    public Book book;    public User() {    }    public User(int userId, String userName, boolean isMale) {        this.userId = userId;        this.userName = userName;        this.isMale = isMale;    }    /**     * 当当前对象中含有文件描述符时,返回1,其他时候返回0;     * @return     */    public int describeContents() {        return 0;    }    /**     * 通过Parcel的write方法,实现序列化     * @param out     * @param flags     */    public void writeToParcel(Parcel out, int flags) {        out.writeInt(userId);        out.writeString(userName);        out.writeInt(isMale ? 1 : 0);        out.writeParcelable(book, 0);    }    /**     * 实现反序列化     */    public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {        /**         * 通过Parcel的read方法,实现反序列化生成一个对象         * @param in         * @return         */        public User createFromParcel(Parcel in) {            return new User(in);        }        /**         * 实现反序列化生成一个数组         * @param size         * @return         */        public User[] newArray(int size) {            return new User[size];        }    };    private User(Parcel in) {        userId = in.readInt();        userName = in.readString();        isMale = in.readInt() == 1;        /**        * book是一个Parcelable对象,反序列需要传递一个ClassLoader,否则会报错。        */        book = in.readParcelable(Thread.currentThread().getContextClassLoader());    }}

其中,序列化时通过writeToParcel()实现,反序列化通过CREATOR提供,内容描述由describeContents提供。注意事项见注释。系统为我们提供了很多Parcelable类:Intent,Bundle和BitMap等。同时,List和Map也可以是Parcelable的,当且仅当它们里面的每个对象都是Parcelable的。

Parcelable和Serializable虽然都是用来序列化的,但是,二者有较大差别。前者用来实现内存序列化,用来在Binder之间传递对象,效率较高,但是使用麻烦。后者是通过读写文件来实现序列化,需要大量的I/O操作,效率低,主要用来序列化对象到存储设备或者网络传送等。

0 0