1. 程式人生 > >Android產品研發(十五)-->記憶體物件序列化

Android產品研發(十五)-->記憶體物件序列化

上一篇文章中我們講解了Android app中的升級更新操作,app的升級更新操作算是App的標配了,升級操作就是獲取App的升級資訊,更新操作是下載,安裝,更新app,其中我們既可以使用app store獲取應用的升級資訊,也可以在應用內通過請求本地伺服器獲取應用的升級資訊,並通過與本地app的版本號對比判斷應用是否需要升級。
升級資訊是app更新的基礎,只有我們的app的升級資訊指明需要更新,我們才可以開始後續的更新操作–也就是下載安裝更新app。這裡強調一點的是應用的升級操作分為普通的升級和強制升級兩種,普通的升級操作就是完成一次對app的更新操作,而強制更新是在線上的app出現bug 的時候一種強制使用者升級的手段,使用者體驗不太好,所以一般不太建議使用這種方式升級使用者的app。
更多關於app升級更新的資訊,可參考我的:

Android產品研發(十四)–>App升級與更新

本文將講解Android中資料傳輸中需要了解的資料序列化方面的知識,我們知道Android開發過程中不同Activity之間傳輸資料可以通過Intent物件的put**方法傳遞,對於java的八大基本資料型別(char int float double long short boolean byte)傳遞是沒有問題的,但是如果傳遞比較複雜的物件型別(比如物件,比如集合等),那麼就可能存在問題,而這時候也就引入了資料序列化的概念。

序列化的定義:

這裡我們先看一下呢序列化在百科上的定義

序列化 (Serialization)將物件的狀態資訊轉換為可以儲存或傳輸的形式的過程。在序列化期間,物件將其當前狀態寫入到臨時或永續性儲存區。以後,可以通過從儲存區中讀取或反序列化物件的狀態,重新建立該物件。

簡單來說就是我們的資料在傳輸的時候需要將資訊轉化為可以傳輸的資料,然後在傳輸的目標方能夠反序列化將資料還原回來,這裡的將物件狀態資訊轉換為可傳輸資料的過程就是序列化,將可傳輸的資料逆還原為物件的過程就是反序列化。

為什麼需要序列化:

知道前面的序列化定義,記憶體物件什麼需要實現序列化呢?

  • 永久性儲存物件,儲存物件的位元組序列到本地檔案。

  • 通過序列化物件在網路中傳遞物件。

  • 通過序列化物件在程序間傳遞物件。

實現序列化的兩種方式:

那麼我們如何實現序列化的操作呢?在Android開發中我們實現序列化有兩種方式:

  • 實現Serializable介面

  • 實現parcelable介面

兩種序列化方式的區別:

都知道在Android studio中序列化有兩種方式:serializable與parcelable。那麼這兩種實現序列化的方式有什麼區別呢?下面是這兩種實現序列化方式的區別:

  1. Serializeble是java的序列化方式,Parcelable是Android特有的序列化方式;

  2. 在使用記憶體的時候,Parcelable比Serializable效能高,所以推薦使用Parcelable。

  3. Serializable在序列化的時候會產生大量的臨時變數,從而引起頻繁的GC。

  4. Parcelable不能使用在要將資料儲存在磁碟上的情況,因為Parcelable不能很好的保證資料的持續性在外界有變化的情況下。儘管Serializable效率低點, 也不提倡用,但在這種情況下,還是建議你用Serializable。

最後還有一點就是Serializeble序列化的方式比較簡單,直接整合一個介面就好了,而parcelable方式比較複雜,不僅需要整合Parcelable介面還需要重寫裡面的方法。

物件實現序列化的例項:

通過實現Serializable介面實現序列化:

上面介紹了那麼多概念上的知識,下面我們就具體看一下如何通過這兩種方式實現序列化,我們首先看一下如何通過實現Serializable介面實現序列化,通過實現Serializable介面實現序列化,只需要簡單的實現Serialiizable介面即可。通過實現Serializable介面就相當於標記型別為序列化了,不需要做其他的操作了。

/**
 * Created by aaron on 16/6/29.
 */
public class Person implements Serializable{

    public static final long serialVersionUID = 1;

    private int age;
    private String name;
    private String address;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

可以發現我們定義了一個普通的實體Person類,並設定了三個成員屬性以及各自的set,get方法,然後我們就只是簡單的實現了Serializable介面就相當於將該類序列化了,當我們在程式中傳輸該型別的物件的時候就沒有問題了。

並且我們在Person類中定義了一個屬性為serialVersionUID的成員變數,這個成員變數是做什麼的呢?
在Java中,軟體的相容性是一個大問題,尤其在使用到物件序列性的時候,那麼在某一個物件已經被序列化了,可是這個物件又被修改後重新部署了,那麼在這種情況下, 用老軟體來讀取新檔案格式雖然不是什麼難事,但是有可能丟失一些資訊。
serialVersionUID來解決這些問題,新增的serialVersionUID必須定義成下面這種形式:

public static final long serialVersionUID=1;

其中數字後面加上的L表示這是一個long值。 通過這種方式來解決不同的版本之間的序列化的問題。

簡單來說就是用serialVersionUID標識class類的版本,當序列化的class原始檔發生變化時,反序列化的一端由於該標識不一致會反序列化失敗,進而保證了兩端原始檔的一致性。

通過實現Parcelable介面實現序列化:

然後我們在看一下通過實現Parcelable介面來實現序列化的方式,通過實現Parcelable介面實現序列化相當於實現Serialiable介面稍微複雜一些,因為其需要實現一些特定的方法,下面我們還是以我們定義的Person類為例子,看一下如果是實現Parcelable介面具體是如何實現的:

/**
 * Created by aaron on 16/6/29.
 */
public class Person implements Parcelable{

    private int age;
    private String name;
    private String address;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

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

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

    public Person() {
    }

    protected Person(Parcel in) {
        this.age = in.readInt();
        this.name = in.readString();
        this.address = in.readString();
    }

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

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}

可以發現當我們通過實現Parcelable介面實現序列化還需要重寫裡面的成員方法,並且這些成員方法的寫法都比較固定。

實現Parcelable序列化的Android studio外掛:

順便說一下最近發現一個比較不錯的Parcelable序列化外掛。下面就來看一下如何安裝使用該外掛。

  • 開啟Android studio –> settings –> Plugins –> 搜尋Parcelable –> Install –> Restart,這樣安裝好了Parcelable外掛;

這裡寫圖片描述

  • 然後在原始檔中右鍵 –> Generate… –> Parcelable

這裡寫圖片描述

  • 點選Parcelable之後可以看到,原始檔中已經實現了Parcelable介面,並重寫了相應的方法:

這裡寫圖片描述

這樣我們就安裝好Parcelable外掛了,然後當我們執行Parcelable操作的時候就重寫了Parcelable介面的相應序列化方法了。

總結:

  • 可以通過實現Serializable和Parcelable介面的方式實現序列化

  • 實現Serializable介面是java中實現序列化的方式,而實現Parcelable是Android中特有的實現序列化的方式,更適合Android環境

  • 實現Serializable介面只需要實現該介面即可無需其他操作,而實現Parcelable介面需要重寫相應的方法

  • Android studio中有實現Parcelable介面的相應外掛,可安裝該外掛很方便的實現Parcelable介面,實現序列化