Android 理解Binder機(jī)制(二)解讀AIDL對應(yīng)的Java文件
本文會結(jié)合上一篇文章:AIDL+Service的簡單使用進(jìn)行對于Android SDK生成的Java文件解讀。
這些類的關(guān)系如下圖所示,在總結(jié)部分還會重新整理:

IBookManager類的結(jié)構(gòu)描述
IBookMananger最開始使我們定義在AIDL文件中的一個接口,他會通過Android SDK工具生成對應(yīng)的Java文件。????其中包括了這樣的一些關(guān)鍵的方法和內(nèi)部類。

Default類
default類在默認(rèn)生成中什么也沒有干:
方法基本上都是空實(shí)現(xiàn)。真正的進(jìn)行業(yè)務(wù)相關(guān)的處理的類在Stub類中,這個類也是我們在Service中需要繼承并且實(shí)現(xiàn)我們的業(yè)務(wù)邏輯。
IBookManager.Stub
上述代碼中有一些需要說明的地方:
asInterface:從注釋中可以知道,將IBinder轉(zhuǎn)換成對應(yīng)的【接口】是區(qū)分進(jìn)程的。如果需要跨進(jìn)程通信,就會調(diào)用Stub的內(nèi)部類,也就是Proxy的方法。
對于是本地Service還是remote service,實(shí)現(xiàn)的區(qū)別略有不同,總結(jié)在下圖中:

remote Service就不再贅述了。如果是本地Service,我們還是需要實(shí)現(xiàn)一個Binder,并且通過Service#onBind進(jìn)行返回。然后在ServiceConnection中,強(qiáng)制類型轉(zhuǎn)換就可以獲取我們的定義的LocalBinder,然后調(diào)用我們的業(yè)務(wù)邏輯。
2.?onTransact:onTransact的回調(diào)主要發(fā)生在跨進(jìn)程通信中。
舉我們的客戶端請求的代碼為例:
這里調(diào)用Manager.getBookList()的實(shí)現(xiàn)就是通過Stub.Proxy中的同名方法實(shí)現(xiàn)的:
在這個個方法中,后面會調(diào)用Binder#transact。大家應(yīng)該還記得在服務(wù)端中的Service中,我們實(shí)現(xiàn)了一個類,繼承自IBookManager.Stub,同時這個Stub也是一個Binder,并且通過Service#onBind返回。這個Remote就是那個實(shí)現(xiàn)類。
在Binder#transact中,后面會回調(diào)onTransact方法:
它的思路是這樣子:
客戶端調(diào)用IBookManager#getBookList -> IBookManager.Stub.Proxy#getBookList -> IBinder#transact -> IBookManager.Stub.onTransact 解析具體的方法。
下面我們具體看看IBookManager.Stub.onTransact:
這個方法對于我們定義咋interface中的方法通過switch-case進(jìn)行處理,比如說getBookList方法,在調(diào)用getBookList進(jìn)行返回。不過this.getBookList的實(shí)現(xiàn)還是在我們的業(yè)務(wù)實(shí)現(xiàn)類中。取出結(jié)果之后,在通過parcel封裝并返回。
總結(jié)
最后總結(jié)一下:
IBookManager.aidl 會通過Android SDK工具生成對應(yīng)名稱的Java文件,這個Java文件中封裝的業(yè)務(wù)邏輯和核心類是Stub
Stub會首先判斷當(dāng)前的接口調(diào)用是否需要跨進(jìn)程,如果不需要跨進(jìn)程,可以直接訪問方法;如果需要跨進(jìn)程就會通過Proxy方法調(diào)用。
在proxy中主要是進(jìn)行一個Parcel的解包和打包的工作,然后會調(diào)用Binder的transact方法,最后回調(diào)Binder#onTransact方法,這個方法運(yùn)行在Binder的線程池中。不需要再業(yè)務(wù)邏輯中進(jìn)行開啟子線程的操作;但是在客戶端中,客戶端發(fā)起遠(yuǎn)程請求時,客戶端線程會被掛起,這里最好別寫在UI線程。
