Serializable和Parcelable的用法


物語.png

導言

做Android開發(fā)的,相信大家都知道,Activity、Fragment之間的數(shù)據(jù)傳遞都是通過Bundle對象進行的。
而Bundle的Api中除了一些基本類型的方法之外,還有兩個特殊的方法:

/**
     * Inserts a Parcelable value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key a String, or null
     * @param value a Parcelable object, or null
     */
    public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
        unparcel();
        mMap.put(key, value);
        mFlags &= ~FLAG_HAS_FDS_KNOWN;
    }

/**
     * Inserts a Serializable value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key a String, or null
     * @param value a Serializable object, or null
     */
    @Override
    public void putSerializable(@Nullable String key, @Nullable Serializable value) {
        super.putSerializable(key, value);
    }

那么,Serializable和Parcelable分別是什么呢?

Serializable

簡介

Serialization是java自帶的類型,做序列化用(把一個對象轉換為可存儲或可傳輸?shù)男问降倪^程),對象可以將其當前狀態(tài)存儲到本地、數(shù)據(jù)庫,也可以在網(wǎng)絡上傳輸。以后,可以從存儲區(qū)中讀取或反序列化對象的狀態(tài),重新創(chuàng)建該對象。
序列化的本質是將運行時的對象轉換為二進制流,保存到流、內存或通過網(wǎng)絡傳輸。

實現(xiàn)方式

對象序列化很簡單,只需要,實現(xiàn)Serialization類。

package com.bs.trade.main.bean;

import java.io.Serializable;

/**
 * author : user_zf
 * date : 18/3/17
 * desc : 茶
 */
public class Tea implements Serializable {
    private static final long serialVersionUID = -1241963366850216618L;
    
    private String name;
    private String price;
    private String describe;

    public String getName() {
        return name;
    }

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

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public String getDescribe() {
        return describe;
    }

    public void setDescribe(String describe) {
        this.describe = describe;
    }
}

看源碼可以發(fā)現(xiàn),Serialization是一個空的接口,它的作用是標志當前類可以被ObjectOutputStream序列化,和被ObjectInputStream反序列化。
可以看到需要定義一個serialVersionUID變量,這個變量類似于接口版本號,標志了唯一一個可序列化的類。序列化過程會保存serialVersionUID,反序列化過程會校驗版本號是否一致,如果不一致,會報InvalidClassException錯誤。
JVM規(guī)范強烈推薦手動聲明一個版本號,AndroidStudio中可以設置Lint提示,自動生成版本號。如果不手動設置這個值,系統(tǒng)會生成一個默認hash值,一旦類結構發(fā)生改變,hash值對應改變,那么反序列化就會校驗serialVersionUID失敗。設置了固定值,即使類結構發(fā)生改變,也能最大程度上保證反序列化成功率。不過如果類名改變,那么反序列化過程中會crash。

用法

public void put() {
    Bundle bundle = new Bundle();
    Tea tea = new Tea();
    tea.setName("普洱");
    tea.setPrice("13");
    tea.setDescribe("清新可口,潤喉滋養(yǎng)");
    bundle.putSerializable("TEA", tea);
}

public void get() {
    Tea tea = (Tea) bundle.getSerializable("TEA");
}

Parcelable

簡介

Parcelable是Android專門提供類,實現(xiàn)的功能和Serialization一樣,就是把對象轉換為可存儲和可傳輸?shù)男问?。不過原理同Serialization不同,Parcelable是把一個完整的對象分進行分解,每一部分都是Intent和Bundle支持的類型。

實現(xiàn)方式

package com.bs.trade.main.bean;


import android.os.Parcel;
import android.os.Parcelable;

/**
 * author : user_zf
 * date : 18/3/17
 * desc : 茶
 */
public class Tea implements Parcelable {
    private String name;
    private String price;
    private String describe;

    public Tea(){}

    private Tea(Parcel source) {
        name = source.readString();
        price = source.readString();
        describe = source.readString();
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeString(price);
        dest.writeString(describe);
    }

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

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

    public String getName() {
        return name;
    }

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

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public String getDescribe() {
        return describe;
    }

    public void setDescribe(String describe) {
        this.describe = describe;
    }
}

要注意的是,字段讀取的順序和寫入的順序必須保持一致。

用法

public void put() {
    Bundle bundle = new Bundle();
    Tea tea = new Tea();
    tea.setName("普洱");
    tea.setPrice("13");
    tea.setDescribe("清新可口,潤喉滋養(yǎng)");
    bundle.putParcelable("TEA", tea);
}

public void get() {
    Tea tea = bundle.getParcelable("TEA");
}

對比Serialization和Parcelable

  1. 在內存中使用的時候,Parcelable比Serialization性能高,推薦使用Parcelable,例如Activity、Fragment數(shù)據(jù)傳遞的場景
  2. Serialization會產(chǎn)生大量的臨時變量,從而引起頻繁的GC。
  3. Parcelable不能使用在將數(shù)據(jù)存儲在磁盤的情況(如SD卡,網(wǎng)絡傳輸),因為Parcelable不能很好的保證數(shù)據(jù)的持續(xù)性,此時推薦使用Serialization。

寫于2018.03.17下午18:00(位置:深圳南山區(qū))

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容