Android:Service之AIDL傳遞複雜物件

來源:互聯網
上載者:User

   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"的泛型靜態屬性,它實現了對象的還原序列化。它也有兩個必須實現的抽象方法:

  abstract T createFromParcel(Parcel source):通過source對象,根據writeToParcel()方法序列化的資料,還原序列化一個Parcelable對象。

  abstract T[] newArray(int size):建立一個新的Parcelable對象的數組。

  例如:

  1 @Override

  2 public int describeContents() {

  3 return 0;

  4 }

  5

  6 @Override

  7 public void writeToParcel(Parcel dest, int flags) {

  8 Log.i("main", "服務端Message被序列化");

  9 dest.writeInt(id);

  10 dest.writeString(msgText);

  11 dest.writeString(fromName);

  12 dest.writeString(date);

  13 }

  14

  15 public static final Parcelable.Creator CREATOR = new Creator() {

  16

  17 @Override

  18 public Message[] newArray(int size) {

  19 return new Message[size];

  20 }

  21

  22 @Override

  23 public Message createFromParcel(Parcel source) {

  24 Log.i("main", "服務端Message被還原序列化");

  25 return new Message(source.readInt(), source.readString(),

  26 source.readString(), source.readString());

  27 }

  28 };

  從上面樣本中可以看出,使用writeToParcel()方法進行序列化,通過CREATOR.createFromParcel進行還原序列化,它們都傳遞一個Parcel類型的對象,這裡要注意的是兩個方法中Parcel對象的writeXxx()和readXxx()方法的順序必須一致,因為一般序列化資料是以鏈的形式序列化的,如果順序不對,還原序列化的資料會出錯。

  AIDL傳遞複雜類型對象Demo

  關鍵點已經講到, 下面通過一個簡單的Demo來示範AIDL傳遞複雜物件。

  AIDL介面:

  com.example.aidlservicedemo.domain.Message.aidl

  Message.aidl

  com.example.aidlservicedemo.domain.Message.java

  Message.java

  com.example.aidlservicedemo.domain.User.aidl

  User.aidl

  com.example.aidlservicedemo.domain.User.java

  User.java

  服務:

  com.example.aidlservicedemo.

  CustomTypeService.java

  用戶端:

  com.example.aidlClientdemo.

  CustomTypeActivity.java

  效果展示:

 

  AIDL傳遞對象序列化過程詳解

  通過上面Demo列印的日誌,解釋一下序列化的過程,開啟Logcat查看日誌。

  從上圖的PID列可以看出這是兩個線程間的互動。

  流程是這樣的,用戶端傳遞一個User對象給服務端,服務端通過User對象處理資料,返回兩個Message對象給用戶端。

  首先,在用戶端傳遞給服務端User對象前,用戶端先把User對象序列化,然後傳遞給服務端之後,服務端接收到的是一段序列化後的資料,它再按照原定的規則對資料進行還原序列化,然後處理User。當服務端查到這個User有兩條Message時,需要傳遞這兩條Message對象給用戶端,在傳遞前對Message對象進行序列化,用戶端收到服務端傳遞過來的序列化後的資料,再根據既定的規則進行還原序列化,得到正確的對象。

  從這個流程可以看出,在進程間傳遞的資料必定是被序列化過的,否則無法傳遞。而對於那些AIDL預設允許傳遞的資料類型(int、double、String、List等),它們其實內部已經實現了序列化,所以無需我們再去指定序列化規則。但是對於複雜類型對象而言,系統無法知道如何去序列化與還原序列化,所以需要我們指定規則。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.