序列化的兩種實現及優劣比較
序列化我們通常會用在Activity之間進行物件傳遞的時候使用到,那麼序列化有兩種,Serializable和Parcelable ,我們該選擇哪一種呢?那就要先知道兩種區別。
1、作用
Serializable的作用是為了儲存物件的屬性到本地檔案、資料庫、網路流、rmi以方便資料傳輸,當然這種傳輸可以是程式內的也可以是兩個程式間的。而Android的Parcelable的設計初衷是因為Serializable效率過慢,為了在程式內不同元件間以及不同Android程式間(AIDL)高效的傳輸資料而設計,這些資料僅在記憶體中存在,Parcelable是通過IBinder通訊的訊息的載體。
從上面的設計上我們就可以看出優劣了。
2、效率及選擇
Parcelable的效能比Serializable好,在記憶體開銷方面較小,所以在記憶體間資料傳輸時推薦使用Parcelable,如activity間傳輸資料,而Serializable可將資料持久化方便儲存,所以在需要儲存或網路傳輸資料時選擇Serializable,因為android不同版本Parcelable可能不同,所以不推薦使用Parcelable進行資料持久化
3、程式設計實現
對於Serializable,類只需要實現Serializable介面,並提供一個序列化版本id(serialVersionUID)即可。而Parcelable則需要實現writeToParcel、describeContents函式以及靜態的CREATOR變數,實際上就是將如何打包和解包的工作自己來定義,而序列化的這些操作完全由底層實現。
然後接下來就是實現了,首先實現Serializable.
這個的實現是何其的簡單,只要繼承一下和宣告一個序列化版本id即可,然後就可以放到bundle裡面使用了,給出;例子:
mport java.io.Serializable;
/**
* Created by 2381144912 on 2017/09/22.
*/
public class newPerson implements Serializable{
private String name;
private int age;
private static final long serialVersionUID = 1L; //序列化id
public newPerson(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
使用時:
person = new Person("小明", "小強", 10);
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelable("Person", person);
intent.putExtras(bundle);
startActivity(intent);
然後接受:
Person person = getIntent().getExtras().getParcelable("Person");
Toast.makeText(this, "" + person.getNickname() + person.getUsername() + person.getAge(), Toast.LENGTH_SHORT).show();
好了,第一種實現了,下面開始Parcelable的實現,這個對前面的來說要重寫幾個方法即可,給出例項:
/**
* Created by 23811 on 2017/09/22.
*/
public class Person implements Parcelable {
private String username;
private String nickname;
private int age;
public Person() {
super();
}
public Person(String username, String nickname, int age) {
super();
this.username = username;
this.nickname = nickname;
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/**
* 這裡的讀的順序必須與writeToParcel(Parcel dest, int flags)方法中
* 寫的順序一致,否則資料會有差錯,比如你的讀取順序如果是:
* nickname = source.readString();
* username=source.readString();
* age = source.readInt();
* 即調換了username和nickname的讀取順序,那麼你會發現你拿到的username是nickname的資料,
* 而你拿到的nickname是username的資料
*
* @param source
*/
public Person(Parcel source) {
username = source.readString();
nickname = source.readString();
age = source.readInt();
}
/**
* 這裡預設返回0即可
*/
@Override
public int describeContents() {
return 0;
}
/**
* 把值寫入Parcel中
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(username);
dest.writeString(nickname);
dest.writeInt(age);
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
/**
* 供外部類反序列化本類陣列使用
*/
@Override
public Person[] newArray(int size) {
return new Person[size];
}
/**
* 從Parcel中讀取資料
*/
@Override
public Person createFromParcel(Parcel source) {
return new Person(source);
}
};
}
註釋很詳細,需要注意的就是我們按什麼順序讀進去的,就要按什麼順序讀出來,否則會亂套,然後是使用:
newPerson = new newPerson("小明", 10);
Intent intent1 = new Intent(MainActivity.this, ThirdActivity.class);
Bundle bundle1 = new Bundle();
bundle1.putSerializable("newPerson", newPerson);
intent1.putExtras(bundle1);
startActivity(intent1);
最後接收:
newPerson person = (newPerson) getIntent().getExtras().getSerializable("newPerson");
Toast.makeText(this, "" + person.getName() + person.getAge(), Toast.LENGTH_SHORT).show();