您好,登錄后才能下訂單哦!
前言:
----IBinder是Android框架的通用性接口,通用性接口意味著,眾人可以共享的接口。由于通用性(或共享性),框架開發者可以藉單一的通用性接口來<包容>形形***的特殊性接口;具有標準化接口的<減法設計>效果,但又不會減損特性用戶或App對特殊性接口的需求。兼顧標準性和特殊性的,是框架通用性接口設計的重要指標;這是任何框架開發里,都必須面對的高度挑戰性任務之一。
高老師陪您成長...
ee ee
從Android的IBinder接口,學習Proxy-Stub設計模式
By 高煥堂
1. IBinder通用性接口
----大家都知道,當兩個類都在同一個進程里執行時,兩者之間的溝通,只要采取一般的函數調用(Function Call)就行了,既快速又方便。一旦兩個類分別在不同的進程里執行時,兩者之間的溝通,就不能采取一般的函數調用途徑了。只好采取IPC溝通途徑。Android框架的IPC溝通仰賴單一的IBinder通用性接口。如下圖:
圖1、Android框架里的IBinder通用性接口
----這種通用性接口,通常會規劃一個抽像基類來實現它;而這抽像基類里則定義了抽象函數。如下圖:
圖2、由Binder基類來實現IBinder通用性接口
于是,這個抽象基類擔任兩項任務:
實現了IBinder接口,這是提供給眾多Client來使用的外部接口。我們以“CI”(Interface for Client)來表示之。
定義了抽象函數,如上圖里的onTransact()函數,成為提供給眾多子類別來實現的內部接口。我們以<I>來表示之。
如下圖所示:
圖3、基類實現CI,并定義<I>
---- 由子類來實現內部接口<I>。Binder基類的很重要目的是支持跨進程調用Service,也就是讓遠程的Client可以跨進程調用某個Service。Binder基類定義于Binder.java檔案里:
// Binder.java
// …….
public class Binder implements IBinder {
// ..........
private int mObject;
public Binder() {
init();
// ...........
}
public final boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
// ................
boolean r = onTransact(code, data, reply, flags);
return r;
}
private boolean execTransact(int code, int dataObj, int replyObj, int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
boolean res;
res = onTransact(code, data, reply, flags);
// ............
return res;
}
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
}
private native final void init();
}
----Binder基類的主要函數是:
transact()函數 --- 用來實作IBinder的transact()函數接口。
execTransact()函數 --- 其角色與transact()函數是相同的,只是這是用來讓C/C++本地程序來調用的。
onTransact()函數 --- 這是一個抽象函數,讓應用子類來覆寫(Override)的。上述的transact()和execTransact()兩者都是調用onTransact()函數來實現反向調用(IoC, Inversion of Control)的。
init()函數 --- 這是一個本地(Native)函數,讓JNI模塊來實現這個函數。Binder()構造函數(Constructor)會調用這個init()本地函數。
如下圖:
圖4、CI與<I>兩個接口的合作
----這個IBinder接口是Binder基類提供給Client的接口,簡稱為“CI”。于是,Client端調用IBinder接口的transact()函數,透過IPC機制而調用到遠方(Remote)的onTransact()函數。
圖5、IBinder接口的主要用途:IPC通信
----其實,這個典型的通用性接口設計模式,還有很多種變化的形式。例如下圖:
圖6、通用性接口設計的變化
----雖然是一個簡單的通用性接口設計模式,但是含有豐富的變化機制。例如上圖的機制,就讓C/C++層的模塊成為架構的掌控者。然而,必須理解到:因為設計(和掌控)了IBinder通用性”接口”設計,才能充分保為了C/C++層的模塊的”邏輯”控制權。
例如,Android跨進程通信流程,都由底層Binder驅動模塊所掌控,如下圖所示:
圖7、底層Binder驅動模塊是IPC的掌控者
2. 通用性接口與Proxy-Stub設計模式
----然而,在上圖里的Activity里可能有多個函數,例如f1()和f2()等。于是,在Activity里,必須從f1()函數轉而調用IBinder.transact()函數。如果我們在上述架構里面,加上一個Stub類別(如下圖的BinderStub類別),它實現了Binder.onTransact()函數,如下圖所示:
圖8、Stub類將通用性接口轉為特殊性接口
----通常,在框架設計里,myProxy和myStub會是成對的,這稱為Proxy-Stub模式。如下圖所示:
圖9、Proxy類將特殊性接口轉換到通用性接口
----采用Proxy-Stub設計模式將IBinder接口包裝起來,讓App與IBinder接口不再產生高度相依性。其將IBinder接口包裝起來,轉換出更好用的新接口,如下圖里的IA接口:
圖10、包裝IBinder接口,轉換出更好用的新接口
----Stub類將onTransact()函數隱藏起來,提供一個更具有美感、更親切的新接口給subBinder類使用。隱藏了onTransact()函數之后,subBinder類的開發者就不必費心去了解onTransact()函數了。于是,Proxy與Stub兩個類遙遙相對,并且將IPC細節知識(例如transact()和onTransact()函數之參數等)包夾起來。由于IBinder接口只提供單一函數(即transact()函數)來進行遠距通信,呼叫起來比較不方便。所以Android提供aidl.exe工具來協助產出Proxy和Stub類別,以化解這個困難。只要你善于使用開發環境的工具(如Android的aidl.exe軟件工具)自動產生Proxy和Stub類別的程序代碼;那就很方便了。 ◆
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。