当我们在进行页面的跳转时,需要通过Intent或者Bundle来传输对象或者集合,这时候就需要序列化将对象转换为可以传输的二进制流。通过Intent或者是Bundle中的源码发现除了可以传输基本数据类型,还可以传输下面两种数据 Parcelable value 以及Serializable value
序列化:将一个对象转换成可存储或可传输的状态(二进制流)。序列化后的对象可以在网络上进行传输,也可以存储到本地。
反序列:将二进制流转换为对象的过程
序列化的主要作用:
1 永久性保存对象,保存对象的字节序列到本地文件中
2 通过序列化对象在网络中传输对象
3 通过序列化对象在进程间传递对象
1 Serializable简介
Serializable是Java中的一个提供序列化的接口,可以为对象提供序列化和反序列化。Serializable接口是一个空接口,使用起来非常方便,只需要将准备序列化的类实现该接口即可。
public interface Serializable {
/* empty */
}
这样子就实现了序列化
public class BookBean implements Serializable{
}
2 Parcelable简介
Parcelable是Android sdk提供的用实现于数据序列化的一个接口,可以为对象提供序列化和反序列化。Paecelable实现的方式略复杂一些,需要重写
describeContents 以及writeToParcel 方法,并且创建一个静态的不可修改的CREATOR 匿名内部类
缺少set 和 get 序列化和反序列话的顺序保持一致 也就是BookBean(Parcel in)以及writeToParcel(Parcel parcel, int i) 顺序保持一致
public class BookBean implements Parcelable {
//基本数据类型
private int bookId;
private String bookName;
private String bookAuthor;
private String bookPrice;
//静态内部对象
private BookSubject bookSubject;
// list 中存放的基本数据类型
private ArrayList<String> tagList;
// list 中存放的是对象
// ***** 注意: 这里如果是集合 ,一定要初始化 *****
private ArrayList<BookSubject> list = new ArrayList<>();
public BookBean() {
}
// 将流转换为对象
public BookBean(Parcel in) {
//读取基本数据类型
bookId = in.readInt();
bookName = in.readString();
bookAuthor = in.readString();
bookPrice = in.readString();
// 读取基本数据的list
tagList = in.createStringArrayList();// 返回 ArrayList<String>
//读取对象 两种方式 第一种读取对象需要提供一个类加载器去读取
// 第二种 传入对象的CREATOR
bookSubject = in.readParcelable(BookSubject.class.getClassLoader());
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// bookSubject = in.readTypedObject(BookSubject.CREATOR);
// }
//读取存放引用对象的list 第一种需要使用类的CREATOR去获取 对应的 writeTypeList
in.readTypedList(list, BookSubject.CREATOR);
//第二种 需要用相应的类加载器去获取 对应writeList
// in.readList(list,BookSubject.class.getClassLoader());
// 这里获取类加载器主要有几种方式
// getClass().getClassLoader();
// Thread.currentThread().getContextClassLoader();
// BookBean.class.getClassLoader();
}
// 负责反序列化
public static final Creator<BookBean> CREATOR = new Creator<BookBean>() {
@Override
public BookBean createFromParcel(Parcel in) {
return new BookBean(in);
}
@Override
public BookBean[] newArray(int size) {
return new BookBean[size];
}
};
@Override
public int describeContents() {
return 0;
}
/**
* 序列化
*/
@Override
public void writeToParcel(Parcel parcel, int i) {
//序列化基本数据类型
parcel.writeInt(bookId);
parcel.writeString(bookName);
parcel.writeString(bookAuthor);
parcel.writeString(bookPrice);
//序列化基本数据类型的list
parcel.writeStringList(tagList);
// 序列化引用对象 这里的flag几乎都是0,除非标识当前对象需要作为返回值返回,不能立即释放资源
parcel.writeParcelable(bookSubject, 0);
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// parcel.writeTypedObject(bookSubject,0);
// }
// 序列化引用类型对象的list
parcel.writeTypedList(list);
}
public static class BookSubject implements Parcelable {
private String subject;
public BookSubject() {
}
protected BookSubject(Parcel in) {
subject = in.readString();
}
public static final Creator<BookSubject> CREATOR = new Creator<BookSubject>() {
@Override
public BookSubject createFromParcel(Parcel in) {
return new BookSubject(in);
}
@Override
public BookSubject[] newArray(int size) {
return new BookSubject[size];
}
};
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(subject);
}
}
}
测试代码快
BookBean bookBean = new BookBean();
//基本数据类型
bookBean.setBookId(1);
bookBean.setBookAuthor("阿萨德");
bookBean.setBookName("水浒传");
bookBean.setBookPrice("¥24");
//引用类型的对象
BookBean.BookSubject bookSubject = new BookBean.BookSubject();
bookSubject.setSubject("巴萨");
bookBean.setBookSubject(bookSubject);
//引用类型对象的数组
ArrayList<BookBean.BookSubject> list = new ArrayList<>();
list.add(bookSubject);
bookBean.setList(list);
//基本数据类型的数组
ArrayList<String> tagsList = new ArrayList<>();
tagsList.add("皇家马德里");
bookBean.setTagList(tagsList);
Intent intent = new Intent(MainActivity.this, MainActivity2.class);
intent.putExtra("testData", bookBean);
startActivity(intent);
BookBean bookBean = getIntent().getParcelableExtra("testData");
//基本数据类型
Log.i("TAG", "onCreate: " + bookBean.getBookAuthor());
//基本数据类型的list
Log.i("TAG", "onCreate: " + bookBean.getTagList().get(0));
//引用类型对象
Log.i("TAG", "onCreate: " + bookBean.getBookSubject().getSubject());
//引用类型对象的list
Log.i("TAG", "onCreate: " + bookBean.getList().get(0).getSubject());
写入和读取集合有两种方式,
一种是写入类的相关信息,然后通过类加载器去读取, –> writeList | readList
二是不用类相关信息,创建时传入相关类的CREATOR来创建 –> writeTypeList | readTypeList | createTypedArrayList
第二种效率高一些
Parcelable和Serializable的区别和比较
Parcelable和Serializable都是实现序列化并且都可以用于Intent间传递数据,
Serializable是Java的实现方式,对象持久化到磁盘,序列化和反序列化需要进行大量的IO操作, 序列化的过程要用到反射,会创建许多的临时变量,容易触发GC,所以消耗比较大,但是实现方式简单
Parcelable是Android提供的方式,效率比较高,但是实现起来复杂一些 , 比Serializable性能高,速度差不多是10倍左右吧
序列化是需要注意两点:
1 静态成员变量属于类不属于对象,所以不参与序列化
2 用transient关键字标记的成员变量不参与序列化
选择序列化方法的原则
1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。
快速实现序列化:
点击完成安装,重启as ,快捷键 Alt + Insert