序列化(Sreilaizbale)定义:
序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
简单来说:
序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
为什么需要序列化:
知道前面的序列化定义,内存对象什么需要实现序列化呢?
-
永久性保存对象,保存对象的字节序列到本地文件。
-
通过序列化对象在网络中传递对象。
-
通过序列化对象在进程间传递对象。
实现序列化的两种方式:
那么我们如何实现序列化的操作呢?在Android开发中我们实现序列化有两种方式:
-
实现Serializable接口
-
实现parcelable接口
两种序列化方式的区别:
都知道在Android studio中序列化有两种方式:serializable与parcelable。那么这两种实现序列化的方式有什么区别呢?下面是这两种实现序列化方式的区别:
-
Serializeble是java的序列化方式,Parcelable是Android特有的序列化方式;
-
在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
-
Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
-
Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点, 也不提倡用,但在这种情况下,还是建议你用Serializable。
最后还有一点就是Serializeble序列化的方式比较简单,直接集成一个接口就好了,而parcelable方式比较复杂,不仅需要集成Parcelable接口还需要重写里面的方法。
为什么要实现对象序列化:
我们知道Android开发过程中不同Activity之间传输数据可以通过Intent对象的putExtra方法传递,对于java的八大基本数据类型(char int float double long short boolean byte)传递是没有问题的,但是如果传递比较复杂的对象类型(比如对象,比如集合等),那么就可能存在问题,就需要实现数据对象数据序列化。
对象实现序列化的实例:
通过实现Serializable接口实现序列化:
上面介绍了那么多概念上的知识,下面我们就具体看一下如何通过这两种方式实现序列化,我们首先看一下如何通过实现Serializable接口实现序列化,通过实现Serializable接口实现序列化,只需要简单的实现Serialiizable接口即可。通过实现Serializable接口就相当于标记类型为序列化了,不需要做其他的操作了。
import java.io.Serializable;
public class PersonOne implements Serializable {
private static final long serialVersionUID = -6009011239477487992L;
private String name;
private int age;
private int id;
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;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
可以发现我们定义了一个普通的实体PersonOne类,并设置了三个成员属性以及各自的set,get方法,然后我们就只是简单的实现了Serializable接口就相当于将该类序列化了,当我们在程序中传输该类型的对象的时候就没有问题了。
现在我们来传递它:
PersonOne personOne = new PersonOne();
personOne.setName("Tom");
personOne.setAge(10);
personOne.setId(1);
Intent intentOne = new Intent(MainActivity.this,SecondActivity.class);
intentOne.putExtra("person_data", personOne);
startActivity(intentOne);
接收它:
PersonOne personOne = (PersonOne) getIntent()
.getSerializableExtra("person_data");
Toast.makeText(this,"Id = "+personOne.getId()+" Name = "
+ personOne.getName() + " Age = "+ personOne.getAge(),Toast.LENGTH_LONG).show();
并且我们在Person类中定义了一个属性为serialVersionUID的成员变量,这个成员变量是做什么的呢?
在Java中,软件的兼容性是一个大问题,尤其在使用到对象串行性的时候,那么在某一个对象已经被串行化了,可是这个对象又被修改后重新部署了,那么在这种情况下, 用老软件来读取新文件格式虽然不是什么难事,但是有可能丢失一些信息。
serialVersionUID来解决这些问题,新增的serialVersionUID必须定义成下面这种形式:
private static final long serialVersionUID = -6009011239477487992L;
其中数字后面加上的L表示这是一个long值。 通过这种方式来解决不同的版本之间的串行化的问题。
简单来说就是用serialVersionUID标识class类的版本,当序列化的class源文件发生变化时,反序列化的一端由于该标识不一致会反序列化失败,进而保证了两端源文件的一致性。
设置Android studio实现Serializable自动生成serialVersionUID步骤:
1、File–>Settings–>Editor–>Inspections–>Java–>Serialization issues–>Serializable class without ‘serialVersionUID’ 勾选中该选项即可。
2、进入实现了Serializable中的类,选中类名,Alt+Enter弹出提示,然后直接导入完成
通过实现Parcelable接口实现序列化:
然后我们在看一下通过实现Parcelable接口来实现序列化的方式,通过实现Parcelable接口实现序列化相当于实现Serialiable接口稍微复杂一些,因为其需要实现一些特定的方法,下面我们还是以我们定义的PersonTwo类为例子,看一下如果是实现Parcelable接口具体是如何实现的:
import android.os.Parcel;
import android.os.Parcelable;
public class PersonTwo implements Parcelable {
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;
}
private String name;
private int age;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
dest.writeInt(this.age);
}
public PersonTwo() {
}
protected PersonTwo(Parcel in) {
this.name = in.readString();
this.age = in.readInt();
}
public static final Creator<PersonTwo> CREATOR = new Creator<PersonTwo>() {
@Override
public PersonTwo createFromParcel(Parcel source) {
return new PersonTwo(source);
}
@Override
public PersonTwo[] newArray(int size) {
return new PersonTwo[size];
}
};
}
可以发现当我们通过实现Parcelable接口实现序列化还需要重写里面的成员方法,并且这些成员方法的写法都比较固定。
传递它:
PersonTwo personTwo = new PersonTwo();
personTwo.setName("Nice");
personTwo.setAge(20);
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("person_two_data",personTwo);
startActivity(intent);
接收它:
PersonTwo personTwo = getIntent().getParcelableExtra("person_two_data");
Toast.makeText(this,"Name = "+personTwo.getName()+
" Age = "+personTwo.getAge(),Toast.LENGTH_LONG).show();
实现Parcelable序列化的Android studio插件:
顺便说一下最近发现一个比较不错的Parcelable序列化插件。下面就来看一下如何安装使用该插件。
打开Android studio –> settings –> Plugins –> 搜索Parcelable –> Install –> Restart,这样安装好了Parcelable插件;
然后你就可以在源文件中右键 –> Generate… –> Parcelable