一、 什么叫序列化?为什么要进行序列化?怎么进行序列化?
1: 什么叫序列化? 序列化:将一个对象转换成可存储或者可传输的状态。序列化后的对象可以在网络上进行传输或者存储到本地。
2: 为什么要进行序列化?在进行Android开发的时候,无法将对象的引用传递给Activity或者Fragments,我们需要将这些对象放到一个Intent
或者Bundle里面,然后在传递。
3: 怎么进行序列化?
Android中Intent如果要传递类对象,可以通过两种方式实现。
方式一:Serializable,要传递的类实现Serializable接口传递对象,
方式二:Parcelable,要传递的类实现Parcelable接口传递对象。
Serializable(Java自带):
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。
Parcelable(android 专用):
除了Serializable之外,使用Parcelable也可以实现相同的效果,
不过不同于将对象进行序列化,Parcelable方式的实现原理是将一个完整的对象进行分解,
而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。
实现Parcelable的作用
1)永久性保存对象,保存对象的字节序列到本地文件中;
2)通过序列化对象在网络中传递对象;
3)通过序列化在进程间传递对象。
选择序列化方法的原则
1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,
但此时还是建议使用Serializable 。
应用场景
需要在多个部件(Activity或Service)之间通过Intent传递一些数据,简单类型(如:数字、字符串)的可以直接放入Intent。
复杂类型必须实现Parcelable接口。
二、利用Java自带Serializable进行序列化的例子:
package com.kelly.parcelableandserializable.bean;
import java.io.Serializable;
/**
* Created by Kelly on 2016/11/25.
*/
public class User implements Serializable {
//指定serialVersionUID,
//因为原则上序列化后的数据中的serialVersionUID只有和当前类的serialVersionUID相同时才能被正常的反序列化
//最好自己指定UID或者系统生成,因为如果增加或者删除了某些成员变量,那么系统就会重新生成hash值然后赋给UID,导致反序列化时候crash
private static final long serialVersionUID = -7060210544600464481L;
private String name;
private int age;
public User(){}
public User(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
三、android专用的Parcelable的序列化的例子
package com.kelly.parcelableandserializable.bean;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by Kelly on 2016/11/25.
*/
public class Book implements Parcelable {
private String name;
private int price;
public Book(){}
/**
* 系统自动添加,给createFromParcel(Parcel in)调用
* @param in
*/
public Book(Parcel in) {
name = in.readString();
price = in.readInt();
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
/**
* 反序列化
*/
public static final Creator<Book> CREATOR = new Creator<Book>() {
/**
*
* @param in
* @return
* createFromParcel()方法中我们要去读取刚才写出的name和age字段,
* 并创建一个Person对象进行返回
* 注意这里读取的顺序一定要和刚才写出的顺序完全相同。
* 读取的工作我们利用一个构造函数帮我们完成了
*/
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0; // 内容接口描述,默认返回0即可。
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(price);
}
@Override
public String toString() {
return "name = " + name + " price = " + price;
}
}
四、Serializable 和Parcelable的对比
编码上:
Serializable代码量少,写起来方便
Parcelable代码多一些
效率上:
Parcelable的速度比高十倍以上
serializable的迷人之处在于你只需要对某个类以及它的属性实现Serializable 接口即可。Serializable 接口是一种标识接口(marker interface),这意味着无需实现方法,Java便会对这个对象进行高效的序列化操作。
这种方法的缺点是使用了反射,序列化的过程较慢。这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收。
Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了