Android --- Serializable 接口与 Parcelable 接口的使用方法和区别,怎么选择?
文章目錄
- 一、前言:
- 二、Serializable 接口
- 三、Parcelable 接口
- 四、兩種接口怎么選擇
一、前言:
本節主要講解 IPC 中的基本概念,Serializable 接口與 Parcelable 接口。
這兩個接口可以完成對象的序列化過程,當我們需要通過 Intent 和 Binder 傳輸數據時就需要使用 Serializable 與 Parcelable 。還有的時候我們需要把對象持久化到存儲設備上或者通過網絡傳輸給其他客戶端,這個時候也需要使用這兩個接口來完成對象的持久化,下面我們一一來介紹。
啥叫對象的持久化?不知道的看下面一句話:
持久化一般指將數據持久化保存,如存到數據庫中或寫到文件中
二、Serializable 接口
Serializable 是 Java所提供的一個序列化接口,這里提到了序列化,那什么叫序列化和反序列化呢?
序列化就是將 Java 對象轉換成二進制文件數據的過程。這樣說可能不是很明白,舉個例子:如果把一個房子比作一個對象,要把這個做房子搬到另外一個地方的話,直接挪動是不現實的,但是可以將房子拆成一個個小零件運輸,到了目的地在組裝成房子,這樣就容易多了,這其中 “拆解” 的過程就是序列化,“重新組裝” 就是反序列化。
說到這里,怎么實現序列化呢?
只需要在類的聲明中指定一個類似下面的標識即可自動實現默認的序列化過程。
全部代碼:
import java.io.Serializable;public class User implements Serializable {private static final long serialVersionUID = 51906712373232662L;public int userId;public String userName;public boolean isMale;public User(int userId, String userName, boolean isMale) {this.userId = userId;this.userName = userName;this.isMale = isMale;} }對象的序列化和反序列化只需要采用 ObjectOutputStream 和 ObjectInputStream 即可輕松實現,如下:
// 序列化過程,就是寫的過程User user = new User(0, "Jack", true);ObjectOutputStream out;{try {out = new ObjectOutputStream(new FileOutputStream("user.txt"));out.writeObject(user);out.close();} catch (IOException e) {e.printStackTrace();}}// 反序列化過程,就是讀的過程ObjectInputStream in;User newUser;{try {in = new ObjectInputStream(new FileInputStream("user.txt"));newUser = (User) in.readObject();in.close();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}現在有個問題,serialVersionUID 是用來輔助序列化和反序列化過程的,原則上序列化后的數據中 serialVersionUID 只有和當前類的 serialVersionUID 相同才能夠正常地被反序列化。不用它行不行,答案:不行。
serialVersionUID 的詳細工作機制是這樣的:序列化的時候系統會把當前的 serialVersionUID 寫入序列化的文件中(也可能是其他中介),當反序列化的時候系統回去檢測文件中的 serialVersionUID ,看它是否和當前類的 serialVersionUID 一致,如果一致就說明序列化類的版本和當前的版本是相同的,這個時候可以成功反序列化;否則就說明當前類和序列化的類相比發生了變化,這個時候是無法反序列化的,會報錯。
再簡單的說就是:反序列化時如果當前類有所改變,比如增加或者刪除了某些成員變量,那么系統就會重新計算當前類的 hash 值并把它賦值給 serialVersionUID ,這個時候當前類的 serialVersionUID 就和序列化的數據中心的 serialVersionUID 不一致,于是反序列化失敗,程序 crash。所以,我們可以明顯感覺到 serialVersionUID 的作用。
Serializable 就介紹到這里了,再加一點比較重要的知識點:靜態成員變量屬于類不屬于對象。所以不會參與序列化的過程,其次使用 transient 關鍵字編輯的成員變量不參與序列化過程。
三、Parcelable 接口
我們在 Android Studio 中寫了一個類 User 實現 Parcelable 接口
public class User implements Parcelable {public int userId;public String userName;public boolean isMale;@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel parcel, int i) {} }這個時候就會爆紅,我們把鼠標放到 User 上面然后按住 "Alt + Enter"鍵會出現下圖的情況,點擊第一個 Add Parcelable Implementation
點擊之后編輯器自動給我們寫了序列化和反序列化過程,非常省事
我們看看全部代碼:
Parcelable 的方法說明
| createFromParcel(Parcel in) | 從序列化后的對象中創建原始對象 | |
| newArray(int size) | 創建指定長度的原始對象數組 | |
| User(Parcel in) | 從序列化后的對象中創建原始對象 | |
| writeToParcel (Parcel out, int flags) | 將當前對象寫入序列化結構中,其中flags標識有兩種值:0或者1(參見右側標記位)。為1時標識當前對象需要作為返回值返回,不能立即釋放資源,幾乎所有情況都為0 | PARCELABLE_WEITE_RETURN VALUE |
| describeContents | 返回當前對象的內容描述。如果含有文件描述符,返回1(參見右側標記位),否則返回0, 幾乎所有情況都返回0 | CONTENTS_FILE_DESCRIPTOR |
四、兩種接口怎么選擇
既然 Parcelable 和 Serializable 都能實現序列化并且都可以用于 Intent 間的數據傳遞,通過二和三我們也知道他們之間的區別了,那么二者該怎么選擇呢?
1.Serializable 是 Java 中的序列化接口,其使用起來開銷比較大,序列化過程有很多 I/O 操作,所以在Java 中我們就采用 Serializable 接口。
2.Parcelable 是 Android 中的序列化方式,因此更適合用在 Android 平臺上,它的缺點就是使用起來比較麻煩,但是它的效率很高,這是 Android 推薦的序列化方式,因此我們要首選 Parcelable。
3.Parcelable 將對象序列化到存儲設備中或者將對象序列化后通過網絡傳輸也都是可以的,但是這個過程會稍微復雜,在 Java 平臺建議用 Serializable,在 Android 平臺建議用 Parcelable 。
部分內容來自安卓開發藝術探索
總結
以上是生活随笔為你收集整理的Android --- Serializable 接口与 Parcelable 接口的使用方法和区别,怎么选择?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Scratch】青少年蓝桥杯_每日一题
- 下一篇: Java 洛谷 P1534 不高兴的津津