一、什么叫序列化?
序列化就是将对象的状态信息转换为可以存储或传输的形式的过程。我们有时候需要进行对象的传输,如果要进行对象的传输我们必须得实现序列化才行。在Android里面实现序列化的方式一般来说有Serializable和Parcelable两种方式,下面我们通过一个简单的小例子来了解下这两种方式吧。
1、Serializable
Serializable是Java提供的一种序列化的方式,使用起来也很简单,直接让我们的实体类实现Serializable接口就可以了,下面我们来新建一个SerializationTest项目开始吧。
首先我们新建一个Student类,然后实现Serializable接口即可。代码如下:
public class Student implements Serializable {
private static final long serialVersionUID = 2198186818507399576L;
private String mName;
private int mAge;
public Student(String name, int age) {
mName = name;
mAge = age;
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public int getAge() {
return mAge;
}
public void setAge(int age) {
mAge = age;
}
}
在这个类里面我们定义了两个全局变量,和普通的实体类没什么两样,唯一的区别是多了个serialVersionUID这个常量,至于这个常量是用来干嘛的,稍后我们再做解释。
下面我们再新建一个SecondActivity活动,然后在MainActivity写一个跳转方法,代码如下:
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Student student = new Student("张三", 20);
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("student", student);
startActivity(intent);
}
});
接下来我们再SecondActivity中接收这个参数:
public class SecondActivity extends AppCompatActivity {
private static final String TAG = "SecondActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = getIntent();
if (intent != null) {
Student student = (Student) intent.getSerializableExtra("student");
Log.d(TAG, "name is: " + student.getName());
Log.d(TAG, "age is: " + student.getAge());
}
}
}
最后我们得到了我们想要的数据,这就是Serializable的基本使用方式。
下面来说一下serialVersionUID的作用,这个值的作用主要是在反序列化的时候起作用,在我们反序列化Java对象的时候必须提供该对象的class文件,如果我们不显示定义这个值的话,系统会根据我们类的信息去自动生成serialVersionUID。有时候我们增加了成员变量或者减少了成员变量,如果没有显示定义serialVersionUID值,系统就会新生成一个serialVersionUID,就会导致serialVersionUID值不一致,最后导致反序列化失败。所以我们在使用Serializable的时候最好手动定义serialVersionUID值,这里值得要注意的是如果我们的类结构发生变化,比如类名改变或者成员变量类型发生变化,这个时候就算显示定义了这个值也会反序列化失败。
1、Parcelable
Parcelable是Android特有的一种序列化方式,使用起来会稍微复杂一点,依旧用上面那个例子来实现一下吧:
public class Student implements Parcelable {
private String mName;
private int mAge;
public Student(String name, int age) {
mName = name;
mAge = age;
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public int getAge() {
return mAge;
}
public void setAge(int age) {
mAge = age;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.mName);
dest.writeInt(this.mAge);
}
protected Student(Parcel in) {
this.mName = in.readString();
this.mAge = in.readInt();
}
public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {
@Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
上面的代码稍微有点复杂,我们先来简单的解释一下吧,当我们序列化的时候会走writeToParcel()这个方法,把对象写入Parcel对象里面去,反序列化则是通过CREATOR来完成的;describeContents()这个方法在通常情况下都是返回0,我们一般不用去管。接下来再将SecondActivity中稍微改动下就可以啦。
public class SecondActivity extends AppCompatActivity {
private static final String TAG = "SecondActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = getIntent();
if (intent != null) {
Student student = intent.getParcelableExtra("student");
Log.d(TAG, "name is: " + student.getName());
Log.d(TAG, "age is: " + student.getAge());
}
}
}
下面来说下这两种序列化方式的区别:
Serializable
优点:使用方式简单。
缺点:资源消耗稍大。
Parcelable
优点:资源消耗小。
缺点:使用方式复杂。
总结:当我们在内存间进行对象传输时,使用Parcelable方式。如果要在存储或网络上进行传输时,使用Serializable。