Android开发-序列化和反序列化的实现 Serializable Parcelable

定义

在Java中的对象序列化指的是将一个Java对象所描述的内容转换为可以存储和传输的形式的过程,通常是将对象转换为字节序列;反序列化就是相反的过程,将字节序列恢复成对象

序列化用途

  • 将对象的字节序列持久化到硬盘中,通常是存放在文件里
  • 进程间通信的时候不能直接传输对象,需将对象以字节序列的形式传输

注意

  • 类里的静态成员变量不属于对象,不会参加序列化
  • 被transient关键字修饰的成员变量不会参与序列化,因为在反序列化的过程中,transient修饰的变量的值会被设置为初始值,比如int型变量会被设置为0,引用型的会被置为null

序列化方法

在Android中实现对象序列化的方法主要有两种

伪序列化

其实有一种伪序列化/反序列化方法,就是使用DataoutputStream/DataInputStream,只不过这种方法需要开发者按顺序一个字段一个字段的进行操作,很反人类;并且不能支持复杂类型数据

	try {
			//序列化
            DataOutputStream dos = new DataOutputStream(new FileOutputStream(filePath));
            OperatorVo bean = new OperatorVo();
            bean.setAge(1);
            bean.setOpername("boy");

            dos.writeInt(bean.getAge());
            dos.writeUTF(bean.getOpername());
            dos.close();
			
			//反序列化
            DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
            bean.setAge(dis.readInt());
            bean.setOpername(dis.readUTF());
            dis.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

实现Serializable接口

Serializable:这是Java提供的一个为对象提供标准的序列化和反序列化的接口,是一个空的接口,没有声明任何方法,开发者只需为自己的对象实现这个接口就行了
这样就能标记这个对象,虚拟机执行序列化指令,就判定该对象可以操作,继而使用ObjectOutputStream进行序列化;反序列化亦是如此

SerialiVersionUID

通常我们实现这个接口的时候,最好指定要给SerialiVersionUID,这是序列化版本号;在进行序列化的时候,会把这个值写入序列化文件,如果没有显示的指定,那么编译器就会自动生成一个;这样在进行反序列化的时候就会检测文件中的SerialiVersionUID与这个类当前的SerialiVersionUID是否相同,如果不同就会反序列化失败,我们在类中增加或者减少字段的时候,自动生成的SerialiVersionUID也会变化,反序列化的时候也会失败;所以开发者最好显示的指定一个SerialiVersionUID

当然你不指定的话不影响序列化,但是可能会影响反序列化

示例

public class Boy implements Serializable{
	private static final long serialVersionUID = 3171346693605985494L;
	private String name;
	private String age;
	.......
}
//序列化
try {
       ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filePath));
       out.writeObject(new Boy());
       out.close();
} catch (IOException e) {
       e.printStackTrace();
}
//反序列化
try {
       ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
       Boyp = (Boy)in.readObject();
       in.close();
 } catch (IOException e) {
       e.printStackTrace();
 }

如果序列化对象里还引用了其它对象,那writeObject方法会进行递归序列化

实现Parcelable接口

Parcelable:是Android提供的序列化接口,通过Parcel写入和恢复数据。
Parcel:它是一个容器,他可以包含数据或者是对象引用,并且能够用于Binder的传输,同时支持序列化以及跨进程之后进行反序列化

示例

public class Boy implements Parcelable{
	
	private String name;
	private int age;

	public Boy() {
		super();
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	/**
	 * 返回当前对象的内容描述,如果含有文件描述符,返回1
	 * 通常返回0
	 */
	@Override
	public int describeContents() {
		return 0;
	}

	/**
	 * 序列化功能由该方法完成,主要是通过Parcel对象的一系列write方法,将本对象的值写到Parcel对象
	 * Parcel类似于使用ObjectOutputStream
	 * 第二个参数有两种值,0和1
	 * 1:如果当前对象需要作为返回值返回,就不能立刻释放资源
	 * 通常情况下为0
	 */
	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeInt(age);
		dest.writeString(name);
	}
	
	/**
	 * 在使用AIDL进行IPC需要这个方法
     * 默认生成的模板类的对象只支持为 in 的定向 tag,因为只有writeToParcel方法
     * 如果要支持为 out 或者 inout 的定向 tag 的话,还需要实现 readFromParcel() 方法
     * 参数是一个Parcel,用它来存储与传输数据
     * 注意,此处的读值顺序应当是和writeToParcel()方法中一致的
     * @param dest
     */
	public void readFromParcel(Parcel dest){
		age = dest.readInt();
		name = dest.readString();
	}
	
	
	public Boy(Parcel parcel){
		age = parcel.readInt();
		name = parcel.readString();
	}
	
	/**
	 * public static final 三个词一个都不能少,并且CREATOR这个名词也不能改变,必须大写
	 * 
	 */
	public static final Creator<Boy> CREATOR = new Creator<Boy>() {
		
		/**
		 * 创建一个类型为T,长度为size的数组,供外部类反序列化本类数组使用
		 */
		@Override
		public Boy[] newArray(int size) {
			return new Boy[size];
		}
		
		/**
		 * 反序列化 读取顺序要与序列化顺序一致
		 * 从Parcel容器中读取数据,封装成对象返回给开发者
		 */
		@Override
		public Boy createFromParcel(Parcel source) {
			return new Boy(source);
		}
	};
}

对比:

  • Serializable实现简单,而Parcelable需要更多的操作
  • Serializable是Java的接口,使用时需要大量I/O操作,开销大,常用于持久化对象到本地;Parcelable效率高,使用麻烦,常用于内存级别的序列化,比如组件间的传输,网络中传输数据,IPC中数据传输等
  • Parcelable为了效率没有考虑更多的兼容性,所以数据持久化操作使用Serializable
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值