Android AIDL使用介绍(2)自定义数据类型的传递
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.使用示例
java代碼里實現Parcelable里的接口,其中值得注意的是writeToParcel方法和readFromParcel方法里面的寫和讀取順序是需要一一對應的,Parcel意為包裹,writeToParcel是快遞打包,作用是獲取對象的當前狀態并將其寫入 Parcel,readFromParcel是拆快遞,打包和拆的順序應一一對應,否則讀取數據會混亂,例如writeToParcel寫數據的順序如下:
則對應的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>() {@Overridepublic Student createFromParcel(Parcel in) {return new Student(in);}@Overridepublic 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>() {@Overridepublic Student createFromParcel(Parcel in) {return new Student(in);}@Overridepublic Student[] newArray(int size) {return new Student[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic 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;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}java文件創建好了之后,則可以開始創建同名的Parcelable類的aidl文件,代碼如下,代碼較簡單,只是聲明Student是parcelable
// Student.aidl package com.pm.service;// Declare any non-default types here with import statements import com.pm.service.Student;parcelable Student;aidl代碼編寫好了之后,記得同步一下工程,然后在Service里實現新增的方法,完整的代碼如下:
package com.pm.service;import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException;import java.util.LinkedList; import java.util.List;public class MyService extends Service {private ServiceAidlInterface.Stub serviceAidlInterface= new ServiceAidlInterface.Stub() {@Overridepublic String ServiceGreet() throws RemoteException {return "Hello Client!";}@Overridepublic List<Student> getStudentList() throws RemoteException {List<Student> list = new LinkedList<>();for (int i = 0; i < 10; i++) {list.add(new Student(i,"s1"+i,"man",i+10));}return list;}};@Overridepublic IBinder onBind(Intent intent) {return serviceAidlInterface.asBinder();} }這樣一來,服務端要做的事都已完成,接下來是客戶端的內容。
客戶端編寫好了之后,運行的效果如下:
4.總結
進程間傳遞自定義對象需要實現Parcelable接口,通過序列化和反序列化實現,相比java原生的Serialization各有特色,如果是數據存儲到磁盤上,建議使用java Serialization,如果是進程間通訊,則使用Parcelable。另外自定義類型的java和aidl文檔要在相同的包名下,否則會提示找不到類的錯誤,自定義類型創建好了之后,便可以像aidl基本數據類型一樣使用。
總結
以上是生活随笔為你收集整理的Android AIDL使用介绍(2)自定义数据类型的传递的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android AIDL使用介绍(1)基
- 下一篇: Android AIDL使用介绍(3)