Android Serializable与Parcelable

来源:互联网 发布:平时穿冲锋衣 知乎 编辑:程序博客网 时间:2024/06/05 11:57

Android Serializable与Parcelable

Serializable与Parcelable是用来保存或传送Java对象

1. 序列化和反序列化

  Java对象包含变量与方法。但是序列与反序列化仅处理Java变量而不处理方法,序列与反序列化仅对数据进行处理。

  • 对象的序列化 : 把Java对象转换为字节序列并存储至一个储存媒介的过程。
  • 对象的反序列化:把字节序列恢复为Java对象的过程。

2. Java对象与Java对象序列化的区别

  Java对象存在的前提必须在JVM运行期间存在,如果想在JVM非运行的情况下或者在其他机器JVM上获取指定Java对象,在现有Java对象的机制下都不可能完成。
  与Java对象不同的是,如果对Java对象执行序列化操作,因为原理是把Java对象信息保存到存储媒介,所以可以在以上Java对象不可能存在的两种情况下依然可以使用Java对象。

3. Android 中Serializable与Parcelable区别与选择原则

  • 区别: 两种都是用于支持序列化、反序列化话操作,两者最大的区别在于存储媒介的不同,Serializable使用IO读写存储在硬盘上,而Parcelable是直接在内存中读写,很明显内存的读写速度通常大于IO读写,所以在Android中通常优先选择Parcelable。
    Serializable不是当前关注的焦点,不过可以查看《Java序列化算法透析》这篇文章中实现一个简单的Serializable例子,查看序列化生成的IO文件,并且以16进制读取并一一解释每一个16进制数字的含义。

  • 选择原则:
    Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存到sd卡或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化。
    Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。在不同app间通过Intent传递对象(不同进程间),不能使用Parcelable,需要使用Serializable,当然最好使用AIDL

4. 代码编写

  对于Serializable,类只需要实现Serializable接口,并提供一个序列化版本id(serialVersionUID)即可,此ID可由系统生成。而Parcelable则需要实现writeToParcel、describeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义,而序列化的这些操作完全由底层实现。

Parcelable举例

public class MyParcelable implements Parcelable {    private int mData;    private String mStr;public int describeContents() {    return 0;} // 写数据进行保存public void writeToParcel(Parcel out, int flags{    out.writeInt(mData);    out.writeString(mStr);} // 用来创建自定义的Parcelable的对象public static final Parcelable.Creator<MyParcelable> CREATOR         = new Parcelable.Creator<MyParcelable>() {     public MyParcelable createFromParcel(Parcel in) {         return new MyParcelable(in);     }     public MyParcelable[] newArray(int size) {         return new MyParcelable[size];     } }; // 读数据进行恢复 private MyParcelable(Parcel in) {     mData = in.readInt();     mStr = in.readString(); }

}

注意:
Parcel的写入和读出顺序需要保持一致。如果元素是list读出时需要先new一个ArrayList传入,否则会报空指针异常。如下:

list = new ArrayList<String>();in.readStringList(list);

Serializable序列化不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObject、readObject方法以实现序列化过程自定义

以下4点摘自《探索Android中的Parcel机制(上)》

  1. 个读写全是在内存中进行,主要是通过malloc()、realloc()、memcpy()等内存操作进行,所以效率比JAVA序列化中使用外部存储器会高很多;
  2. 读写时是4字节对齐的,可以看到
    #define PAD_SIZE(s) (((s)+3)&~3) 这句宏定义就是在做这件事情;
  3. 如果预分配的空间不够时newSize = ((mDataSize+len)*3)/2;会一次多分配50%;
  4. 对于普通数据,使用的是mData内存地址,对于IBinder类型的数据以及FileDescriptor使用的是mObjects内存地址。后者是通过flatten_binder()和unflatten_binder()实现的,目的是反序列化时读出的对象就是原对象而不用重新new一个新对象。

转自:
http://www.cnblogs.com/trinea/archive/2012/11/09/2763213.html
http://www.2cto.com/kf/201403/288476.html

0 0
原创粉丝点击