Android序列化相关(使用Serializable还是Parcelable?)

这篇文章将从《Android开发艺术探索》中总结学习Android序列化相关的内容。

文章目录:

  • 序列化是什么?为什么需要序列化?
  • 实现方式
    • Serializable接口(SerializableUID的必要性)
    • Parcelable接口
  • 两者的区别及使用场景

序列化是什么?为什么需要序列化?

序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。
序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。
通俗的来讲:序列化是将对象存储为二进制格式


为什么要把对象序列化?
序列化是将对象转换为容易传输的格式的过程,是为了解决在对对象流进行读写操作时所引发的问题。

对象序列化的两个使用场景:

  • 对象持久化:将对象的状态持久化,比如存储到数据库中。
  • 对象远程传输:将对象从一台计算机发送到另外一台计算机。

实现方式

Serializable接口

Serializable是java所提供的一个序列化接口,它是一个空接口,为对象提供标准的序列化和反序列化操作。

想要对一个对象实现序列化,只需要这个类实现Serializable接口(并声明SerializableUID,SerializableUID不是必需的,但是关于它的必要性下边会讲到)。

public class User implements Serializable{
	private static final long SerializableUID =1L;
	public int userId;
	……
}

通过Serializable方式来实现对象的序列化和反序列化实现起来也很简单:只需要采用ObjectOutputStream和ObjectInputStream即可实现。

//序列化过程
User user = new User(0,"jack");
ObjectOutputStream out =new ObjectOutputStream(new FileOutputStream(cache.txt));
out.writeObject(user);
out.close();

//反序列化过程     (回复后的对象newUser和user的内容完全一样,但是两者并不是同一个对象)
ObjectInputStream in =new ObjectInputStream(new FileInputStream(cache.txt));
User newUser=(User)in.readObject();
in.close();

SerializableUID的必要性

即使我们不指定SerializableUID也可以实现序列化,那到底要不要指定呢?
回答:有必要指定,SerializableUID可以避免反序列化过程的失败

SerializableUID是用来辅助序列化和反序列化过程的。原则上只有反序列化后的数据中的SerializableUID和当前类的SerializableUID相同才能正常的被反序列化。

SerializableUID的工作机制:

  • 序列化的时候系统会把当前类的SerializableUID写入序列化的文件中
  • 反序列化的时候系统会去检测文件中的SerializableUID,看它是否和当前类的SerializableUID一致,如果一致就说明序列化的类的版本和当前类的版本是相同的,这个时候就可以成功反序化;否则说明当前类和序列化好的类相比发生了某些变化(比如成员变量的数量,类型可能发生了变化),这个时候是无法正常反序列化的。

当我们手动的制定了SerializableUID之后,就可以很大程度上避免反序列化过程的失败(比如版本升级后,我们可能删除了某个成员变量也可能增加了一些成员变量,这个时候我们反序列化过程仍然能成功)。
如果类的机构发成了非常规性改变(比如修改了类名,修改了成员变量的类型),这时候尽管SerializableUID验证通过了,但反序列化过程还是会失败,因为类结构有了毁灭性的改变。

Parcelable接口

Parcelable是Android提供的新的序列化方式。Parcelable也是一个接口。只要实现这个接口,一个类的对象就可以实现序列化并可以通过Intent和Binder传递。

//Parcelable接口使用
public class User implements Parcelabe{
	public int userId;
	public String userName;
	
 	public User(int userId,String userName){
 		this.userId=userId;
 		this.userName=userName;
 	}
 	public int describeCobtents(){
 		return 0;
 	}
 	public void writeToParcel(Parcel out ,int flags){
 		out.writeInt(userId);
 		out.writeStrin(userName);
 	}

	public static final Parcelable.Creator<User> CREATOR =new Parcelable.Creator<User>(){
		public User createFrromParcel(Parcel in){
			return new User(in);
		}
		public User[] newArray(int size){
			return new suer[size];
;		}
	};
	
	private User(Parcel in){
		userId=in.readInt();
		userName=in.readString();
	}
}

两者的区别及使用场景

Serializable和Parcelable都能实现序列化并且都可以用于Intent键的数据传递,那么二者如何选取呢?

  • Serializable是Java提供的序列化接口,使用起来简单但是开销很大,因为序列化和反序列化过程需要大量的I/O操作;
  • Parcelable虽然使用起来稍微麻烦一些,但是他的效率高,是Android推荐的序列化方式。

使用场景:

  • 只进行序列化操作,用于应用内数据的传输则使用Parcelable,因为他效率高
  • 需要持久化或网络传输则建议使用Serializable,因为Parcelable比较复杂。

你可能感兴趣的:(Android)