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