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接口,實現序列化


另外對產品研發技術,技巧,實踐方面感興趣的同學可以參考我的:
Android產品研發(一)–>實用開發規範
Android產品研發(二)–>啓動頁優化
Android產品研發(三)–>基類Activity
Android產品研發(四)–>減小Apk大小
Android產品研發(五)–>多渠道打包
Android產品研發(六)–>Apk混淆
Android產品研發(七)–>Apk熱修復
Android產品研發(八)–>App數據統計
Android產品研發(九)–>App網絡傳輸協議
Android產品研發(十)–>不使用靜態變量保存數據
Android產品研發(十一)–>應用內跳轉scheme協議
Android產品研發(十二)–>App長連接實現
Android產品研發(十三)–>App輪訓操作
Android產品研發(十四)–>App升級與更新


本文以同步至github中:https://github.com/yipianfengye/AndroidProject,歡迎star和follow


發佈了125 篇原創文章 · 獲贊 932 · 訪問量 149萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章