Android重修課 — Serializable&Parcelable

Leon之發表於2019-02-26

1. 從序列化開始說起

首先我們來看看什麼是序列化。
序列化是指將資料結構物件轉換成可取用格式(例如存成檔案,存於緩衝,或經由網路中傳送),以留待後續在相同或另一臺計算機環境中,能恢復原先狀態的過程。反序列化就是序列化的逆向過程。

在我看來,實際意義上的序列化指的是將記憶體中的物件通過某種方式轉變成為資料流的過程。至於將形成的資料流存於檔案或者通過網路傳輸應該是另外一個的話題了。

2. 那麼為什麼需要序列化

很多資料物件我們在記憶體中可以使用,然後如果存在跨執行緒、跨程式、跨記憶體甚至跨主機的時候想要使用相同物件的話。我們就需要一個將資料傳送過去的過程,這個過程我們可以將記憶體中的物件轉化成資料流物件,通過儲存到本地檔案之類的方法傳遞到將要被使用的地方。而在java中,就為我們提供了從記憶體物件轉換成資料流這樣的方案,Serializable

3. 普通的序列化方式是什麼呢

Serializable是java提供的標準的序列化和反序列化的介面。它是一個空介面,為物件提供標準的序列化和反序列化操作。優點是使用方便,只需要實現serializable介面即可。代價是在序列化和反序列化的時候,會使用到反射,並且會建立許多臨時物件,導致更多的gc,導致效能不佳。

我們來看看它的使用方式

public class UserInfo implements Serializable {

    private static final long serialVersionUID = 1L;
    public String userId;
    public String name;
    public int age;

}
複製程式碼

就像上面程式碼所示,我們只需要實現Serializable即可,並指定一個serialVersionUID即可。實際上,serialVersionUID並不是必要的,我們也可以不指定,因為這個UID只是用於輔助序列化和反序列化過程,說白了,就是一個標識,表明我們在序列化和反序列化的操作針對的是同一種型別。

4. 為什麼有了Serializable我們還需要使用Parcelable呢

在Android系統中,我們元件與元件之間,程式與程式之間也是需要通訊的,需要將記憶體中的物件傳遞。當然Serializable是可以實現這個功能的。然後Serializable是有它的缺點的,使用Serializable的序列化和反序列化的時候,會使用到反射,並且會建立許多臨時物件,導致更多的gc,導致效能不佳。所以在Android中,內建了一個更加高效優雅的序列化和反序列方式,Parcelable

5. Parcelable是什麼

是Android sdk提供的序列化介面。是通過安卓系統的Parcel機制來進行序列化和反序列化。

使用方式

public class UserInfo implements Parcelable {

    public String userId;
    public String name;
    public int age;

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.userId);
        dest.writeString(this.name);
        dest.writeInt(this.age);
    }

    public UserInfo() {
    }

    protected UserInfo(Parcel in) {
        this.userId = in.readString();
        this.name = in.readString();
        this.age = in.readInt();
    }

    public static final Parcelable.Creator<UserInfo> CREATOR = new Parcelable.Creator<UserInfo>() {
        @Override
        public UserInfo createFromParcel(Parcel source) {
            return new UserInfo(source);
        }

        @Override
        public UserInfo[] newArray(int size) {
            return new UserInfo[size];
        }
    };
}
複製程式碼

6. 為什麼Parcelable會比Serializable更高效呢

因為Parcelable實現序列化的方法是通過Parcel來實現的,我們在實現Parcelable介面的時候,需要自己編寫程式碼實現writeToParcel()createFromParcel()的過程,所以說Parcelable是通過自定義轉換的方式來實現序列化和反序列過程。其中不會產生垃圾,效果就會比Serializable更好。如果我們把實現Serializable的方式改成自己實現writeObject()readObject(),那麼兩者效率不會相差太大。

7. 那在Android開發中是不是可以完全使用Parcelable替代Serializable呢

答案是不一定的,關鍵還是要看你物件的使用場景,如果你的記憶體物件只需要在Android元件中,或者Android程式之間傳遞使用的話,使用Parcelable效果是更好的。如果你的記憶體物件可能被儲存到本地或者傳輸到網路中的話,使用Serializable是更加有保證性的。

相關文章