国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android序列化之Parcelable和Serializable的使用詳解

2019-10-22 18:17:51
字體:
來源:轉載
供稿:網友

序列化與反序列

首先來了解一下序列化與反序列化。

序列化

由于存在于內存中的對象都是暫時的,無法長期駐存,為了把對象的狀態保持下來,這時需要把對象寫入到磁盤或者其他介質中,這個過程就叫做序列化。

反序列化

反序列化恰恰是序列化的反向操作,也就是說,把已存在在磁盤或者其他介質中的對象,反序列化(讀取)到內存中,以便后續操作,而這個過程就叫做反序列化。

概括性來說序列化是指將對象實例的狀態存儲到存儲媒體(磁盤或者其他介質)的過程。在此過程中,先將對象的公共字段和私有字段以及類的名稱(包括類所在的程序集)轉換為字節流,然后再把字節流寫入數據流。在隨后對對象進行反序列化時,將創建出與原對象完全相同的副本。

實現序列化的必要條件

一個對象要實現序列化操作,該類就必須實現了Serializable接口或者Parcelable接口,其中Serializable接口是在java中的序列化抽象類,而Parcelable接口則是android中特有的序列化接口,在某些情況下,Parcelable接口實現的序列化更為高效,關于它們的實現案例我們后續會分析,這里只要清楚知道實現序列化操作時必須實現Serializable接口或者Parcelable接口之一即可。

序列化的應用情景

主要有以下情況(但不限于以下情況)

1)內存中的對象寫入到硬盤;
2)用套接字在網絡上傳送對象;
3)通過RMI(Remote Method Invoke 遠程方法調用)傳輸對象;

1.Parcelable和Serializable有什么用,它們有什么差別?

Parcelable和Serializable是兩個接口,它們的作用是讓實現了其中一個接口的類的對象能夠被序列化和反序列化。

(1)Serializable是java提供的序列化接口,它是一個空的接口,僅標識該類型可序列化的,具體的序列化/反序列化工作由 ObjectInputStream(readObject)/ObjectOutputStream(writeObject) 完成,這個過程包含大量的I/O操作,使用比較簡單,但需要考量性能的影響。使用場景:將對象持久化到存儲介質或者通過網絡傳輸。

(2)Parcelable接口是Android平臺下的序列化接口,通常跨進程傳遞的數據都要正確實現這個接口,比如Intent,Bitmap等。Parcelable實現起來比Serializable復雜,但性能較好。使用場景:在內存中實現序列化,例如跨進程傳遞。若某個字段不需要序列化,在實現 writeToParcel 方法中忽略此字段即可。

2.自定義一個類讓其實現Parcelable,大致流程是什么?

(1)首先實現Parcelable接口,并實現接口中的方法。

/** * 返回當前對象的內容描述,如果有文件描述符返回1,否則返回0。 */@Overridepublic int describeContents() { return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) { dest.writeInt(userId); dest.writeString(userName); dest.writeInt(isMan ? 1 : 0);}

(2)接著創建一個Parcelable接口內部的接口類型Creator的一個成員,內部需要用到一個帶一個Parcel參數的構造方法。

protected User(Parcel in) { userId = in.readInt(); userName = in.readString(); isMan = in.readByte() != 0;}/** * 在aidl中,參數使用in或者inout來修飾時,服務端的onTransact()會調用CREATOR中方法來反序列化客戶端傳過來的參數 */public static final Creator<User> CREATOR = new Creator<User>() { @Override public User createFromParcel(Parcel in) {  return new User(in); } @Override public User[] newArray(int size) {  return new User[size]; }};

(3)如果在aidl文件中使用out或者inout定向tag來修飾參數,還必須實現一個 readFromParcel(Parcel) 方法,這是因為使用這兩個定向tag修飾的參數,在服務端onTransact()返回后,客戶端會調用 readFromParcel() 來讀取(反序列化)_reply中的數據。該方法與writeToParcel是對應的,實現如下:

public void readFromParcel(Parcel in) { userId = in.readInt(); userName = in.readString(); isMan = in.readInt() == 1 ? true : false;}

3.實現Serializable接口

通過實現Serializable接口來實現序列化比較簡單,只需要實現該接口,并指定 serialVersionUID 即可,當然這個ID是可選的,可以不手動指定。通過ObjectIntputStream /ObjectOutputStream來序列化和反序列化。

ObjectOutputStream oos = null;try { oos = new ObjectOutputStream(new FileOutputStream(new File("sdcard/user.cache"))); User user = new User(111, "Jdqm", true); oos.writeObject(user);} catch (IOException e) { e.printStackTrace();} finally { try {  oos.close(); } catch (IOException e) {  e.printStackTrace(); }}
ObjectInputStream ois = null;try { ois = new ObjectInputStream(new FileInputStream(new File("sdcard/user.cache"))); User user = (User) ois.readObject(); Log.d(TAG, "user: " + user);} catch (IOException | ClassNotFoundException e) { e.printStackTrace();} finally { try {  ois.close(); } catch (IOException e) {  e.printStackTrace(); }}

輸出結果

User{userId=111, userName='Jdqm', isMan=true}

serialVersionUID的意義:輔助完成序列化和反序列化,當一個類實現SerSerializable接口,沒有添加serialVersionUID的作用字段時,IDE會發出警告,這個字段可以手動指定一個值,比如1L,也可指定為IED根據類的結構生成一個long值,它們的效果是一樣的。在序列化時會將這個值寫入存儲介質,反序列化時就校驗本地類的serialVersionUID和序列化介質中的是否一致,不一致將拋出異常 java.io.InvalidClassException

(1)若不指定:系統會根據類的結構計算出一個serialVersionUID,一旦類的結構發生改變這個值就會改變,將導致反序列化失敗;

(2)指定一個值:當類的結構發生改變時,也可以不修改serialVersionUID的值,這種情況下能最大程度上通過反序列化回復數據,若類的結構發生毀滅性的改變,例如字段數據類型改變了,也會導致反序列失敗。

Note: 類的結構發生改變指的是類的成員變量的改變,添加一個普通的方法是不會導致計算得到的serialVersionUID改變的。構造方法、toString()、getter/setter改變會引起serialVersionUID改變。

  1. transient修飾的成員變量不參與序列化,反序列化時改成員為該數據類型的默認值
  2. 靜態成員不參與序列化
  3. 反序列化得到的一個新對象的過程并沒有調用構造方法

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 疏附县| 积石山| 鄯善县| 昭通市| 南澳县| 香港| 武山县| 苗栗市| 丰县| 扶沟县| 灵寿县| 会东县| 固原市| 出国| 醴陵市| 惠来县| 新晃| 信阳市| 闽清县| 鲁甸县| 博乐市| 德化县| 增城市| 齐河县| 科尔| 台中县| 古浪县| 城口县| 荔波县| 博湖县| 邵东县| 珠海市| 怀柔区| 河北区| 南安市| 松潘县| 福海县| 门源| 松潘县| 田林县| 田林县|