Android序列化和反序列化開發(fā)精要

Serializable - Java原生的序列化方案
Parcelable - android提供的序列化方案

Serializable接口的使用

空接口,類只需要聲明 implements Serializable, 并提供一個serialVersionUID值即可.
使用ObjectOutputStreamd和ObjectInputStream就可以把一個對象寫入文件和從文件讀取出來.
寫入文件:

LoggingInfo logInfo = new LoggingInfo("MIKE", "MECHANICS");
FileOutputStream fos = new FileOutputStream("c:\\logging.obj");  
ObjectOutputStream oos = new ObjectOutputStream(fos);  
oos.writeObject(logInfo);  
oos.close();

讀取文件:

FileInputStream fis = new FileInputStream("c:\\logging.obj");  
ObjectInputStream ois = new ObjectInputStream(fis);  
LoggingInfo info = (LoggingInfo) ois.readObject();  
ois.close();
提供serialVersionUID值的目的

系統(tǒng)序列化和反序列化時, 使用這個值來判斷在這2次操作之間, 類的結(jié)構(gòu)是否發(fā)生了變化。
如果不提供這個值的話, 系統(tǒng)會根據(jù)當(dāng)前類的結(jié)構(gòu)自動生成serialVersionUID值,如果serialVersionUID的值發(fā)生了變化,
或者即便serialVersionUID兩次相同, 但由于類結(jié)構(gòu)發(fā)生的變化(例如:改變了類中某個成員變量的類型)導(dǎo)致無法完成反序列化操作, 系統(tǒng)會報異常終止操作.

靜態(tài)成員變量和transient標(biāo)記的變量不參與序列化

靜態(tài)成員變量屬于類不屬于對象, 因此不參與序列化過程.
有些敏感變量值, 比如用戶的密碼不希望被序列化, 就可以用transient標(biāo)記而不參與序列化.

Parcelable接口的使用

使用起來稍顯復(fù)雜, 需要自己實現(xiàn)3個方法:

writeToParcel(Parcel dest, int flags)
內(nèi)部接口Creator里的createFromParcel(Parcel source)
describeContents()

Demo:

 public class MyParcelable implements Parcelable {
     private int mData;

     public int describeContents() {
         return 0;
     }

     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mData); //通過Parcel的一系列write方法實現(xiàn)序列化
     }

     public static final Parcelable.Creator<MyParcelable> CREATOR
             = new Parcelable.Creator<MyParcelable>() {
         public MyParcelable createFromParcel(Parcel in) {
             return new MyParcelable(in);//內(nèi)部實現(xiàn)上, 通過Parcel的一系列read方法實現(xiàn)反序列化
         }

         public MyParcelable[] newArray(int size) {
             return new MyParcelable[size];
         }
     };

     private MyParcelable(Parcel in) {
         mData = in.readInt();
     }
 }

Parcelable接口最常見的用處.

如果某個類的對象需要設(shè)置給Intent中的Bundle對象, 那么這個類要實現(xiàn)Parcelable或Serializable接口.
通?;谛士紤], 這個類選擇實現(xiàn)Parcelable接口.

public class Intent implements Parcelable, Cloneable {
    private Bundle mExtras;

    public Intent putExtra(String name, Parcelable value) {
        mExtras.putParcelable(name, value);
        return this;
    }

    public Intent putExtra(String name, Serializable value) {
            mExtras.putSerializable(name, value);
            return this;
    }
}

Bundle其實就是一個保存K,V數(shù)據(jù)的Map.

/**
 * Bundle Class
 * A mapping from String K to various Parcelable types V.
 *
 */
public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
}
Serializable接口和Parcelable接口都能實現(xiàn)序列化,選擇哪個?

Parcelable主要用于把對象序列化后,以K,V的形式設(shè)置給intent中的bundle.這個intent對象攜帶著這個數(shù)據(jù),
傳遞給其他進程使用, 實現(xiàn)跨進程的數(shù)據(jù)傳遞.

Intent intent = new Intent();
intent.putExtra("downloadParam", mDownloadParam);

雖然通過Parcelable也可以實現(xiàn)把對象寫入存儲設(shè)備或是把對象序列化后通過網(wǎng)絡(luò)傳輸,
但實現(xiàn)起來比較復(fù)雜, 因此這兩種情況下一般還是使用Serializable接口.

Android里面為什么要設(shè)計出Bundle而不是直接讓Intent使用Map結(jié)構(gòu)承載數(shù)據(jù)

Map里實現(xiàn)了Serializable接口,而Bundle實現(xiàn)了Parcelable的接口.
基于執(zhí)行效率的考慮(比 JDK 自帶的 Serializable 效率高),讓Intent使用Bundle結(jié)構(gòu).
宏觀上說, Bundle實際上就是一個特殊的Map.

intent傳遞數(shù)據(jù)時,數(shù)據(jù)大小的限制在1Mb以內(nèi)

因此不要使用intent直接傳遞bitmap對象, 否則容易發(fā)生crash.
詳見:
http://blog.csdn.net/a568078283/article/details/46681321

----DONE.-----------

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容