范例解析:学习Android的IPC主板模式
一、認識Android的IPC主板模式
??系統架構設計最關鍵的任務就是組合(或稱整合),而且最好是能與眾不同、深具創新性組合。Android就擅用了主板模式,以通用性接口實踐跨進程的IPC通信機制。由于Android是開源開放的系統,其源代碼可成為大家觀摩的范本。首先,其主板模式提供了IBinder通用性接口。如下圖:?
? ?
??Android定義一個Binder父類來實現<通用性>的IBinder接口。如下圖:
? ???
? 然后,以Java來撰寫這個實現類,其Java代碼如下:
?
// Android的源代碼
// 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();
}
// End
?
這個Binder抽象父類的主要函數:?
?transact()函數-- 用來實作IBinder的transact()函數接口。
?execTransact()函數--?其角色與transact()函數是相同的,只是這是用來讓C/C++本地程序來調用的。
?onTransact()函數-- 這是一個抽象函數,讓應用子類來覆寫(Override)的。上述的transact()和execTransact()兩者都是調用onTransact()函數來實現反向調用(IoC,?Inversion?of?Control)的。
?init()函數-- 這是一個本地(Native)函數,讓JNI模塊來實現這個函數。Binder()構造函數(Constructor)會調用這個init()本地函數。
這Binder.java是抽象類,它含有一個抽象)函數:onTransact()。于是,這個軟件主板提供了兩個接口:CI和<I>接口。如下圖:
? ?
這是標準型的主板模式。此圖里的Binder抽象父類和兩個接口,整合起來成為一個典型的軟件主板。如下圖:?
? ?
? ?這個Binder軟件主板是用來整合兩個進程里的軟件模塊(如類),所以我們稱之為:<Android的IPC軟件主板>。如下圖:
? ?
? ?基于這個主板,我們就能開始進行組合了。此時,可設計一個子類,并且裝配到主板的<I>接口上。如下圖:
? ? ? ??
? ??? ?這個IBinder接口是Binder基類提供給Client的接口,簡稱為“CI”。于是,Client端調用IBinder接口的transact()函數,進而調用到Binder抽象類的onTransact()函數。如果Client類與Binder類是執行于同一個進程里,Client端調用IBinder接口的transact()函數,進而調用到Binder抽象類的onTransact()函數。反之,如果Client類與Binder類分別執行于不同的兩個進程里,Client端則調用Binder類的exeTransact()函數,透過IPC機制而調用到遠方的onTransact()函數。例如,下圖里的Activity與Binder之間是跨進程的遠距通信(IPC)。如下圖:
? ? ???
? Android的IPC機制是透過底層Binder驅動來實現的,所以會從底層的C/C++函數來調用exeTransact()函數,再轉而調用<I>接口的onTransact()函數。如下圖:
? ? ??
? ? ? ?Android跨進程通信流程,都由底層Binder驅動模塊所掌控。于是,Java層的Activity就能透過底層來調用Binder父類的exeTransact()函數。如下圖所示:?
?
二、主板模式與Proxy-Stub模式的組合應用
??????在上圖里的Activity里可能有多個函數,例如f1()和f2()等。于是,在Activity里,必須從f1()函數轉而調用IBinder.transact()函數。如果我們在上述架構里面,加上一個Stub類別(如下圖的BinderStub類別),它實現了Binder.onTransact()函數,如下圖所示:?
???
?? ? ???通常,在框架設計里,myProxy和myStub會是成對的,這稱為Proxy-Stub模式。如下圖所示:?
? ? ???
???????采用Proxy-Stub設計模式將IBinder接口包裝起來,讓App與IBinder接口不再產生高度相依性。其將IBinder接口包裝起來,轉換出更好用的新接口,如下圖里的IA接口:??
? ???
??Stub類將onTransact()函數隱藏起來,提供一個更具有美感、更親切的新接口給subBinder類使用。隱藏了onTransact()函數之后,subBinder類的開發者就不必費心去了解onTransact()函數了。于是,Proxy與Stub兩個類遙遙相對,并且將IPC細節知識(例如transact()和onTransact()函數之參數等)包夾起來。由于IBinder接口只提供單一函數(即transact()函數)來進行遠距通信,呼叫起來比較不方便。所以Android提供aidl.exe工具來協助產出Proxy和Stub類別,以化解這個困難。只要你善于使用開發環境的工具(如Android的aidl.exe軟件工具)自動產生Proxy和Stub類別的程序代碼;那就很方便了。◆
~ End ~?
總結
以上是生活随笔為你收集整理的范例解析:学习Android的IPC主板模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring利用JDBCTemplate
- 下一篇: 快速安装及部署DRBD