Android中的序列化和反序列化
序列化和反序列化是跨进程通信的基础。其存在的意义在于,可把自定义类转化为某种公认的存储格式进行传输,并保证传输前后自定义类的可解析性。
对于Android来说,存在两者实现方式,Serializable和Parcelable。Serializable是java自带的接口。而Parcelable是Android专门提供的接口。我们在Intent中传递Bundle数据就实现了Parcelable接口。
Serializable
Serializable使用起来非常简单,只需要将自定义类implements Serializable即可,且没有任何需要实现的方法。
举个简单的例子
public class User implements Serializable{ private static final long serialVersionUID=1l; private String mName; private int mAge; public User(String mName, int mAge) { this.mName = mName; this.mAge = mAge; } public String getmName() { return mName; } public int getmAge() { return mAge; } public void setmName(String mName) { this.mName = mName; } public void setmAge(int mAge) { this.mAge = mAge; }}
注意到类中存在serialVersionUID字段,该变量是optional的。区别在于,
(1)如果不设定,在序列化时,将自动添加该字段,并把类结构的Hash赋值给该字段。当反序列化时,对比Hash,若一致,则解析,不一致,则抛出异常。
(2)如果设定,在反序列化出现异常时(例如,添加或删除了某些字段),最大程度的完成对数据的解析,若仍不可解析,则抛出异常。
Parcelable
Parcelable接口相对Serializable要复杂些,需要完成对几个方法的实现。直接来看个例子。
public class User implements Parcelable { private String mName; private int mAge; public User(String mName, int mAge) { this.mName = mName; this.mAge = mAge; } protected User(Parcel in) { mName = in.readString(); mAge = in.readInt(); } public static final Creator CREATOR = new Creator() { @Override public User createFromParcel(Parcel in) { return new User(in); } @Override public User[] newArray(int size) { return new User[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mName); dest.writeInt(mAge); } public String getmName() { return mName; } public int getmAge() { return mAge; } public void setmName(String mName) { this.mName = mName; } public void setmAge(int mAge) { this.mAge = mAge; }}
(1)describeContents()方法,用于表述。通常不用修改,直接返回0。
(2)public void writeToParcel(Parcel dest, int flags)方法,用于将自定义类进行序列化。
(3)protected User(Parcel in)构造方法,用于反序列化,将序列化数据解析为自定义类。
(4)Parcelable.Creator字段,实际是对protected User(Parcel in)构造方法的调用,用于从序列化数据中转化自定义类。
需要注意的是writeToParcel中的字段写入顺序,要与protected User(Parcel in)中的字段读取顺序一致,否则将解析失败。
对比
从实现上来看,Parcelable比Serializable繁琐。但如果使用Android Studio自动生成的话,倒也无所谓。
从效率上来说,Parcelable为Android专用,效率高,而Serializable会调用大量的IO接口,开销大。
从适用场景来说,Parcelable多运用于进程间的数据传递,而Serializable更适用于以文件为载体的网络传输。
附录
附带Serializable读取和写入例子
public void writeSerializable() { try { // 构造对象 User user = new User("breakloop",1); // 构造序列化输出字节流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("xxx.txt")); // 序列化对象 oos.writeObject(book); // 关闭流 oos.close(); } catch (Exception e) { e.printStackTrace(); }}public void readSerializable() { try { // 创建序列化读取字节流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("xxx.txt")); // 反序列化(读取)对象 User user = (User) ois.readObject(); // 关闭流 ois.close(); } catch (Exception e) { e.printStackTrace(); }}
更多相关文章
- Android四大基本组件(Activity,Service,Content Provider 和 Broadc
- Android原生和H5、JS交互,使用JsBridge
- iOS开发之分页控件的简单封装
- 如何在Android中利用AIDL添加service
- Android(Xamarin)之旅(五)
- Android(安卓)invalidate 与postInvalidate用法
- Android中Intent,service,broadcast应用浅析
- Android事件分发与消费
- Android(安卓)图片压缩也即生成缩略图方法