AIDL傳遞復雜類型對象的特殊處理
前面已經介紹了通過AIDL接口在進程間傳遞系統允許的數據,如果需要傳遞一個復雜類型的對象,就沒那么簡單了,需要額外做一些處理。如下:
定義數據接口的AIDL文件中,使用parcelable關鍵字,例如:parcelable Message;
在其數據實現類中實現Parcelable接口,并實現對應的方法。
在業務接口的AIDL文件中,使用import引入數據接口AIDL的包名。
例如:Message.aidl
1 parcelable Message;
例如:IGetMsg.aidl
1 package com.example.aidlservicedemo.domain;
2
3 // 這是兩個自定義類
4 import com.example.aidlservicedemo.domain.Message;
5 import com.example.aidlservicedemo.domain.User;
6
7 interface IGetMsg{
8 // 在AIDL接口中定義一個getMes方法
9 List getMes(in User us);
10 }
Parcelable與Parcel接口
先來說說Android對象序列化,在Android中序列化對象主要有兩種方式,實現Serializable接口或是實現Parcelable接口。Serializable接口是JavaSE原生支持的,而Parcelable接口是Android所特有的,它的序列化和反序列化的效率均比Serializable接口高,而AIDL進行在進程間通信(IPC),就是需要實現這個Parcelable接口。
Parcelable接口的作用:實現了Parcelable接口的實例,可以將自身的數據信息寫入一個Parcel對象,也可以從parcel中恢復到對象的狀態。而Parcel就是完成數據序列化寫入的載體。
上面提到Parcel,再來聊聊Parcel是什么?Android系統設計之初,定位就是針對內存受限的設備,因此對性能要求更好,所以系統中采用進程間通信(IPC)機制,必然要求性能更優良的序列化方式,所以Parcel就被設計出來了,其定位就是輕量級的高效的對象序列化機制與反序列化機制。如果讀一下Android的底層代碼,會發現Parcel是使用C++實現的,底層直接通過Parcel指針操作內存實現,所以它的才更高效。
Parcel也提供了一系列的方法幫助寫入數據與讀取數據,這里簡單介紹一下:
obtain():在池中獲取一個新的Parcel。
dataSize():得到當前Parcel對象的實際存儲空間。
dataPostion():獲取當前Parcel對象的偏移量。
setDataPosition():設置當前Parcel對象的偏移量。
recyle():清空、回收當前Parcel對象的內存。
writeXxx():向當前Parcel對象寫入數據,具有多種重載。
readXxx():從當前Parcel對象讀取數據,具有多種重載。
簡單來說,Parcelable通過writeToParcel()方法,對復雜對象的數據寫入Parcel的方式進行對象序列化,然后在需要的時候,通過其內定義的靜態屬性CREATOR.createFromParcel()進行反序列化的操作。Parcelable對Parcel進行了包裝,其內部就是通過操作Parcel進行序列化與反序列化的。
Parcelable與Parcel均定義在android.os包下,而這種機制不僅用于AIDL,還可以用于Intent傳遞數據等其他地方,這不是本篇博客的主題,以后用到再詳細介紹。
實現Parcelable接口
定義好數據接口的AIDL文件后,需要定義一個數據實現類,實現Parcelable接口,并實現對應的方法,Parcelable有如下幾個必須要實現的抽象方法:
abstract int describeContents():返回一個位掩碼,表示一組特殊對象類型的Parcelable,一般返回0即可。
asbtract void writeToParcel(Parcel dest,int flags):實現對象的序列化,通過Parcel的一系列writeXxx()方法序列化對象。
除了上面兩個方法,還需要在實現類中定義一個名為"CREATOR",類型為"Parcelable.Creator"的泛型靜態屬性,它實現了對象的反序列化。它也有兩個必須實現的抽象方法:
新聞熱點
疑難解答