一、什麼叫序列化?
序列化就是將對象的狀態信息轉換爲可以存儲或傳輸的形式的過程。我們有時候需要進行對象的傳輸,如果要進行對象的傳輸我們必須得實現序列化才行。在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。