對AIDL和Binder的理解

Zhongyi_Li發表於2020-10-13

AIDL只是方便開發者使用Binder的“工具”,Binder是用來跨程式呼叫的。如果沒有AIDL,自己寫Binder實現跨程式通訊還是挺麻煩的,而且都是重複性的程式碼。

服務端:

會有一個Binder子類Stub的例項,Stub需要繼承Binder,重寫onTransact方法。這個Binder例項接受遠端請求,進入onTransact方法處理,在onTransact中是需要能呼叫具體處理程式碼,其實通過組合的方式也是可以的,Binder中擁有IBookManager的例項,不過AIDL中是通過繼承的方式實現的,具體看Stub類。
需要說明的是:一個Binder例項是需要能查詢自己是否關聯一個IInterface的,IBookManager實現了IInterface,其實就是看Binder是否關聯一個業務介面。查詢介面是在IBinder中定義的IInterface queryLocalInterface(String descriptor)。在Binder中提供了一個方法attachInterface把IInterface存入Binder中。(在這裡學習到了一個程式設計思想:IBinder中只定義了查詢介面,沒有定義放入介面,說明只讓外部使用者查詢,讓子類建立者解決怎麼放)

為啥要讓Binder有查詢是否關聯一個IInterface的能力呢?

這是因為客戶端也是有個Binder的,如何知道這個Binder表示的是本地的還是遠端的,只需要查詢一下Binder是否關聯一個業務介面,如果關聯,說明是本地Binder直接返回這個介面,如果沒有關聯一個業務介面,說明是一個遠端Binder,我們需要代理Proxy來包裝一下遠端Binder,讓客戶端能直接操作業務介面一樣的使用IPC。這塊內容看一下Stub的public static com.lzy.learnpro.IBookManager asInterface(android.os.IBinder obj)

再說一個IIterface

這個介面很簡單

/**
 * Base class for Binder interfaces.  When defining a new interface,
 * you must derive it from IInterface.
 */
public interface IInterface
{
    /**
     * Retrieve the Binder object associated with this interface.
     * You must use this instead of a plain cast, so that proxy objects
     * can return the correct result.
     */
    public IBinder asBinder();
}

其實就是讓因為介面能返回相關聯的Binder。在服務端返回的就是本地Binder,看Stub原始碼,在客戶端返回的就是遠端Binder,看Proxy原始碼。

Service和Binder的關係

AIDL只是方便使用Binder,也可以不用AIDL。在IPC的時候是需要使用Service的,通過啟動後Service才能獲取到遠端Binder,這樣就可以通訊了。不過還是使用AIDL更方便些,客戶端啟動繫結Service後在onServiceConnected獲取到Binder,通過Stub的asInterface能很簡單的轉化成對應的業務介面,具體看上面的分析。

客戶端

客戶端就很簡單了,繫結Service後,獲取一個Binder,通過Stub的asInterface把Binder轉化成業務介面,這樣就可以通訊了。

相關文章