近來在使用Android序列化的時候遇到一些問題因此這裏記錄一下,一個不當心你面試就可能面上了。面試
何時使用序列化?bash
Android中實現序列化有兩個選擇:一是實現Serializable接口(是JavaSE自己就支持的),一是實現Parcelable接口(是Android特有功能,效率比實現Serializable接口高效,可用於Intent數據傳遞,也能夠用於進程間通訊(IPC))。實現Serializable接口很是簡單,聲明一下就能夠了,而實現Parcelable接口稍微複雜一些,但效率更高,在通常的時候推薦用這種方法提升性能。架構
###Parcelable和Serializable的區別ide
1)在使用內存的時候,Parcelable比Serializable性能高,因此推薦使用Parcelable,除了如下介紹的坑問題。組件化
2)Serializable在序列化的時候會產生大量的臨時變量,從而引發頻繁的GC。性能
3)Parcelable不能使用在要將數據存儲在磁盤上的狀況,由於Parcelable不能很好的保證數據的持續性在外界有變化的狀況下。儘管Serializable效率低點,但此時仍是建議使用Serializable 。學習
1.可是會有特殊的時候,例如如下代碼有什麼問題?ui
public class Person implements Parcelable {
public String name;
public int age;
public List<Person> childlist;
protected Person(Parcel in) {
name = in.readString();
age = in.readInt();
childlist = in.createTypedArrayList(Person.CREATOR);
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
dest.writeTypedList(childlist);
}
}
複製代碼
估計一眼看不出有什麼問題,問題就在於若是List childlist若是包含了當前的Person對象,序列化的時候,就會致使循環引用,一直序列化直到棧溢出,因此這裏須要很是當心。有些時候爲了代碼抽象方便,極可能就會所以忽視了一些問題。spa
2.ParcelIn和writeToParcel的讀和寫的順序須要是一致的,否則序列化會出錯。code
3.每次新加入屬性,須要記得手動再次生成Parceble相應的方法。AS編譯器生成是最穩的,別做死本身寫。
4.抽象繼承傳遞問題。 Person抽象類方法
public abstract class Person implements Parcelable {
public String name;
public int age;
public List<Person> childlist;
protected Person(Parcel in) {
name = in.readString();
age = in.readInt();
childlist = in.createTypedArrayList(Person.CREATOR);
job = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
dest.writeTypedList(childlist);
dest.writeString(job);
}
@Override
public int describeContents() {
return 0;
}
abstract String getJob();
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in) {
@Override
String getJob() {
return "";
}
};
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
}
複製代碼
Father實類
public class Father extends Person{
public String job;
protected Father(Parcel in) {
super(in);
}
@Override
String getJob() {
return "soft engineer";
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest,flags);
}
}
複製代碼
這樣一開始看沒什麼問題,能夠正常傳遞。可是使用intent傳遞的時候,通過序列化後頗有可能會數據丟失。由於抽象方法致使,某些數據序列化失敗。
這種場景有兩種解決方法
1.使用Serializable來序列化
2.將序列化操做移動到父類進行。
固然若是你有更好的寫法能夠聯繫我吧。
我創建了一個關於Android架構學習的羣,裏面能夠進一步進行組件化學習和架構思想的的交流。
羣號是316556016,也能夠掃碼進羣。我在這裏期待大家的加入!!!