搬運自csdn博主風行南方
1.背景
默認情況下,AIDL只支持下列數據類型:
- Java八種基礎數據類型(如 int、long、char、boolean 等);
- String字符串;
- CharSequence字符序列;
- List列表,List中的所有元素須是前面提到的數據類型,或者是Parcelable類型(這也是本文准備講解的);
- Map,Map 中的所有元素必須是以上列表中支持的數據類型,或者您所聲明的由 AIDL 生成的其他接口或Parcelable 類型;
如果想在進程間傳遞以上數據類型之外的對象該怎么辦?這就需用到Parcelable接口,Parcelable意思是“可包裹的”,是Android系統可用的序列化接口的一種,另外一種是來自java的Serialable,和Parcelable相比,Serialable的使用較為簡單,如果只是保存數據到本地這類應用,使用Serialable即可,但在進程間通訊,則建議使用Parcelable。
2.序列化和反序列化
Parcelable是序列化接口,那么什么是序列化,為什么進程間傳輸自定義對象需要使用序列化?百度百科對序列化的定義如下:
序列化是將對象的狀態信息轉換為可以存儲或傳輸的形式的過程。在序列化期間,對象將其當前狀態寫入到臨時或持久性存儲區。之后,可以通過從存儲區中讀取或反序列化對象的狀態,重新創建該對象。
數據在內存中是字節形態,數據分解到最后都是0和1字節流,這就像萬物分解到最后都是原子一樣,進程A要傳遞數據給進程B,同樣是以字節形式傳遞,對於基本數據類型,例如進程A傳遞int類型數據給進程B,因為進程A和進程B都知道int類型,因此進程B可以直接從內存中還原出數據,而對於自定義數據類型,例如進程A自定義了一個Student對象,進程B並不知道,如果直接傳遞字節流給進程B,面對一堆字節流,進程B不知道怎么重構還原,需要進程A告訴重構方法,這便是序列化和反序列化的過程,這也是傳遞自定義對象需使用序列化的原因。
3.使用示例
- 服務端創建自定義類型,這包括創建Student.java和Student.aidl,兩個文件分別在aidl目錄下和java目錄下,但兩個文件所在的包名必須相同,否則編譯不通。
java代碼里實現Parcelable
里的接口,其中值得注意的是writeToParcel方法和readFromParcel方法里面的寫和讀取順序是需要一一對應的,Parcel意為包裹,writeToParcel是快遞打包,作用是獲取對象的當前狀態並將其寫入 Parcel,readFromParcel是拆快遞,打包和拆的順序應一一對應,否則讀取數據會混亂,例如writeToParcel
寫數據的順序如下:
public void writeToParcel(Parcel dest, int flags) { dest.writeInt(id);//寫一個int類型的值 dest.writeString(name);//寫一個String類型的值 dest.writeString(gender);//寫一個String類型的值 dest.writeInt(age);//寫一個int類型的值 }
則對應的readFromParcel
應按照相應的順序讀取
public void readFromParcel(Parcel source) { id = source.readInt(); name = source.readString(); gender = source.readString(); age = source.readInt(); }
另外,自定義類型中必須含有一個名稱為CREATOR
的靜態成員,該成員是實現 Parcelable.Creator 接口的對象,用於從Parcel生成Parcelable的實例。
public static final Creator<Student> CREATOR = new Creator<Student>() { @Override public Student createFromParcel(Parcel in) { return new Student(in); } @Override public Student[] newArray(int size) { return new Student[size]; } };
完整的自定義類型java代碼如下:
package com.pm.service; import android.os.Parcel; import android.os.Parcelable; public class Student implements Parcelable { private int id; private String name; private String gender; private int age; protected Student(Parcel in) { id = in.readInt(); name = in.readString(); gender = in.readString(); age = in.readInt(); } public Student(int id, String name, String gender, int age) { this.id = id; this.name = name; this.gender = gender; this.age = age; } public Student(){} public static final Creator<Student> CREATOR = new Creator<Student>() { @Override public Student createFromParcel(Parcel in) { return new Student(in); } @Override public Student[] newArray(int size) { return new Student[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(id); dest.writeString(name); dest.writeString(gender); dest.writeInt(age); } public void readFromParcel(Parcel source) { id = source.readInt(); name = source.readString(); gender = source.readString(); age = source.readInt(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name