[架構基本功]Parcelable序列化

Android組件化架構

近來在使用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,也能夠掃碼進羣。我在這裏期待大家的加入!!!

Android組件化架構

組件化架構2羣
相關文章
相關標籤/搜索