一.简介
Android中,实现序列化有两种实现方式。实现Serializable接口和实现Parcelable接口两种方式。
实现Serializable接口 是JavaSE本身就支持的。实现Parcelable接口 是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC)。
实现Serializable接口非常简单,声明一下就可以了,而实现Parcelable接口稍微复杂一些,但效率更高,Android中推荐用这种方法提高性能。
实现Parcelable或是Serializable就是为了进行序列化,那么,为什么要序列化?
(1)永久性保存对象,保存对象的字节序列到本地文件中。
(2)通过序列化对象在网络中传递对象。
(3)通过序列化在进程间传递对象。
选择序列化方法的原则
(1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
(2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
(3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。
注:Android中Intent传递对象有两种方法:
一种是:Bundle.putSerializable(Key,Object)
一种是:Bundle.putParcelable(Key,Object)。
当然这些Object是有一定的条件的,前者是实现了Serializable接口,而后者是实现了Parcelable接口。注意intent传递对象有大小限制,一般是1M。
二.代码实现
1.Serializable实现
package com.example.rxjava20.serialization;
import java.io.Serializable;
/**
* 图书实体类 Serializable接口实现序列化
*/
public class Books implements Serializable {
private int bookId;
private String bookName;
private String bookLabel;
private float bookPrice;
public int getBookId() {
return bookId;
}
public void setBookId(int bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getBookLabel() {
return bookLabel;
}
public void setBookLabel(String bookLabel) {
this.bookLabel = bookLabel;
}
public float getBookPrice() {
return bookPrice;
}
public void setBookPrice(float bookPrice) {
this.bookPrice = bookPrice;
}
@Override
public String toString() {
return "Books{" +
"bookId=" + bookId +
", bookName='" + bookName + '\'' +
", bookLabel='" + bookLabel + '\'' +
", bookPrice=" + bookPrice +
'}';
}
}
Serializable的实现,只需要 implements Serializable 即可。这只是给实体类打了一个标记,系统会自动将其序列化。
2.Parcelabel实现
package com.example.rxjava20.serialization;
import android.os.Parcel;
import android.os.Parcelable;
/**
* 图书实体类 Parcelable接口实现序列化
*/
public class Book implements Parcelable {
private int bookId;
private String bookName;
private String bookLabel;
private float bookPrice;
public Book() {
}
/**
* 构造方法 可按报错提示自动生成
*/
protected Book(Parcel in) {
bookId = in.readInt();
bookName = in.readString();
bookLabel = in.readString();
bookPrice = in.readFloat();
}
/**
* Creator对象 可按报错提示自动生成
*/
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
public int getBookId() {
return bookId;
}
public void setBookId(int bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getBookLabel() {
return bookLabel;
}
public void setBookLabel(String bookLabel) {
this.bookLabel = bookLabel;
}
public float getBookPrice() {
return bookPrice;
}
public void setBookPrice(float bookPrice) {
this.bookPrice = bookPrice;
}
/**
* 实现Parcelable接口 重写的方法
*/
@Override
public int describeContents() {
return 0;
}
/**
* 实现Parcelable接口 重写的方法
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(bookId);
dest.writeString(bookName);
dest.writeString(bookLabel);
dest.writeFloat(bookPrice);
}
@Override
public String toString() {
return "Book{" +
"bookId=" + bookId +
", bookName='" + bookName + '\'' +
", bookLabel='" + bookLabel + '\'' +
", bookPrice=" + bookPrice +
'}';
}
}
Parcelabel的实现,不仅需要 implements Parcelabel,还需要在类中添加一个静态成员变量CREATOR,这个变量需要实现 Parcelable.Creator 接口。
步骤
<1> 按照正常创建实体类的方法,设置各种值,然后set/get各种方法。
<2> 实体类实现Parcelabel接口。重写两个必须重写的方法。
/**
* 实现Parcelable接口 重写的方法
*/
@Override
public int describeContents() {
return 0;
}
/**
* 实现Parcelable接口 重写的方法
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(bookId);
dest.writeString(bookName);
dest.writeString(bookLabel);
dest.writeFloat(bookPrice);
}
<3> 按照步骤2重写上述两个方法后,还提示添加一个构造方法和一个对象。
/**
* 构造方法 可按报错提示自动生成
*/
protected Book(Parcel in) {
bookId = in.readInt();
bookName = in.readString();
bookLabel = in.readString();
bookPrice = in.readFloat();
}
/**
* Creator对象 可按报错提示自动生成
*/
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
三个步骤就可以实现使用Parcelable接口实现序列化了。注意按照常规方法创建实体类后,添加相关get/set方法后。按照提示完成步骤2和步骤3即可。不需要手写。
3.Activity调用
package com.example.rxjava20.serialization;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import com.example.rxjava20.R;
public class SerializationActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_serialization);
Book book = new Book();
book.setBookId(123456);
book.setBookLabel("Parcelable接口实现序列化-图书标签");
book.setBookName("Parcelable接口实现序列化-图书名称");
book.setBookPrice(56.78f);
Log.d("SerializationActivity", "Parcelable接口实现序列化 实体类内容:" + book.toString());
Books books = new Books();
books.setBookId(654321);
books.setBookLabel("Serializable接口实现序列化-图书标签");
books.setBookName("Serializable接口实现序列化-图书名称");
books.setBookPrice(87.65f);
Log.d("SerializationActivity", "Serializable接口实现序列化 实体类内容:" + books.toString());
}
}
4.结果
D/SerializationActivity: Parcelable接口实现序列化 实体类内容:Book{bookId=123456, bookName='Parcelable接口实现序列化-图书名称', bookLabel='Parcelable接口实现序列化-图书标签', bookPrice=56.78}
D/SerializationActivity: Serializable接口实现序列化 实体类内容:Books{bookId=654321, bookName='Serializable接口实现序列化-图书名称', bookLabel='Serializable接口实现序列化-图书标签', bookPrice=87.65}