概要:介紹綁定服務端的三種方式:同一進程綁定服務、跨進程綁定服務(Messenger)、跨進程綁定服務(aidl)。 重點說一下通過Messenger、Service實現的進程間通信。
基礎:AIDL(Android Interface Definition Language)——進程間通信的一種機制。它允許您定義客戶端和服務端通過使用進程間通信(IPC)進行通信的編程接口。在Android上,一個進程無法正常訪問另一個進程的內存。所以說,他們需要將他們的對象分解成操作系統能夠理解的原語,并且把這些對象放在你的邊界上。編寫這些代碼非常繁瑣,所以Android使用AIDL來處理它。
使用場景:
在創建提供綁定的Service時,必須提供一個IBinder (客戶端可以用來與服務進行交互的編程接口)。有三種方法可以定義接口:
1、擴展Binder類
如果您的Service對您自己的應用程序是私有的,并且與客戶端在相同的進程中運行(這是常見的),則應該通過擴展Binder類并創建其實例,onBind()返回該實例。 客戶端收到Binder,可以使用它直接訪問Binder實現或甚至Service中可用的公共方法。
當您的服務只是您自己的應用程序的后臺工作者時,這是首選技術。您不會以這種方式創建界面的唯一原因是因為您的服務被其他應用程序或單獨的進程使用。
2、使用Messenger
如果您需要Service 和客戶端位于不同的進程,則可以使用Messenger為服務創建一個interface。 以這種方式,服務定義響應不同類型的Message對象的Handler。 該Handler是Messenger的基礎,可以與客戶端共享IBinder,允許客戶端使用Message對象向服務發送命令。 此外,客戶端可以定義自己的Messenger,因此服務可以發回消息。
這是執行進程間通信(IPC)的最簡單的方法,因為Messenger將所有請求排隊到單個線程中,以便您不必將服務設計為線程安全。
3、使用AIDL
AIDL(Android Interface Definition Language)執行所有的工作,將對象分解為基元,操作系統可以在進程之間了解和編組它們以執行IPC。 之前使用的Messenger技術實際上是基于AIDL作為其底層結構。 如上所述,Messenger在單個線程中創建所有客戶端請求的隊列,因此服務一次接收一個請求。 但是,如果您希望您的服務同時處理多個請求,則可以直接使用AIDL。 在這種情況下,您的服務必須能夠進行多線程并建立線程安全。
要直接使用AIDL,您必須創建一個定義編程接口的.aidl文件。 Android SDK工具使用此文件生成一個實現接口并處理IPC的抽象類,然后您可以在服務中擴展它。
注意:大多數應用程序不應該使用AIDL創建綁定的服務,因為它可能需要多線程功能,并可能導致更復雜的實現。因此,AIDL不適用于大多數應用程序。
異同:
- Messenger本質也是AIDL,只是進行了封裝,開發的時候不用再寫.aidl文件。
結合我自身的使用,因為不用去寫.aidl文件,相比起來,Messenger使用起來十分簡單。但前面也說了,Messenger本質上也是AIDL,故在底層進程間通信這一塊,兩者的效率應該是一樣的。
- 在service端,Messenger處理client端的請求是單線程的,而AIDL是多線程的。
使用AIDL的時候,service端每收到一個client端的請求時,就會啟動一個線程(非主線程)去執行相應的操作。而Messenger,service收到的請求是放在Handler的MessageQueue里面,Handler大家都用過,它需要綁定一個Thread,然后不斷poll message執行相關操作,這個過程是同步執行的。
- client的方法,使用AIDL獲取返回值是同步的,而Messenger是異步的。
Messenger只提供了一個方法進行進程間通信,就是send(Message msg)方法,發送的是一個Message,沒有返回值,要拿到返回值,需要把client的Messenger作為msg.replyTo參數傳遞過去,service端處理完之后,在調用客戶端的Messenger的send(Message msg)方法把返回值傳遞回client,這個過程是異步的,而AIDL你可以自己指定方法,指定返回值,它獲取返回值是同步的。
其實,第二點是有辦法解決的,在service端,Messenger的Handler可以只當作一個轉發器,不處理請求,只轉發請求到相應的處理線程(多是相應的HandlerThread),這樣也可以達到異步的效果。