在《Android框架式編程之EventBus》 和 《Android 開發框架 EventBus 原理解析》 中,明確了如何使用EventBus作為事件總線,簡化Android各個組件的通信復雜度,並了解了其實現原理。但是EventBus只限於同一個進程中,如果想要在多個進程之間也能像EventBus一樣這樣使用,此時可以借用餓了么開源的HermesEventBus這個框架。
一、HermesEventBus 框架介紹
HermesEventBus 框架倉庫地址:https://github.com/Xiaofei-it/HermesEventBus。
HermesEventBus 擁有 EventBus 全部的作用和相同的 API (內部依賴EventBus) ,其主要作用就是基於 EventBus 實現的進程間通信,這個框架基於兩個庫開發:Hermes和EventBus。事件收發是基於EventBus,IPC通信是基於Hermes。
二、HermesEventBus 實現跨進程通信的原理
Hermes是一個簡單易用的Android IPC庫。HermesEventBus 先選一個進程作為主進程,將其他進程作為子進程。每次一個event被發送都會經過以下四步:
1、使用Hermes庫將event傳遞給主進程。
2、主進程使用EventBus在主進程內部發送event。
3、主進程使用Hermes庫將event傳遞給所有的子進程。
4、每個子進程使用EventBus在子進程內部發送event。
其實現方案的原理圖如下:
通過這種方式,能實現在單一進程內進行多進程開發,也可以實現跨App實現Event事件收發。
三、HermesEventBus 使用方式
1. 單一App內使用HermesEventBus的方式
在單一app內進行多進程開發,那么只需要做以下三步:
首先,在gradle文件中加入下面的依賴:
dependencies { compile 'xiaofei.library:hermes-eventbus:0.3.0' }
然后,在Application的onCreate中加上以下語句進行初始化:
HermesEventBus.getDefault().init(this);
最后,在每次使用EventBus的時候,用HermesEventBus代替EventBus。
HermesEventBus.getDefault().register(this); HermesEventBus.getDefault().post(new Event());
HermesEventBus也能夠在一個進程間傳遞event,所以如果你已經使用了HermesEventBus,那么就不要再使用EventBus了。
當進程不需要再發送和接受event的時候,那么這個進程必須調用:
HermesEventBus.getDefault().destroy();
否則你會收到android.os.DeadObjectException
和其他一些異常。這些異常會打印一些異常信息但不會導致app崩潰。
2. 多個App內使用HermesEventBus的方式
如果你想在多個app間收發event,那么就做如下幾步:
首先,在每個app的gradle文件中加入依賴:
dependencies { compile 'xiaofei.library:hermes-eventbus:0.3.0' }
然后,選擇一個app作為主app。你可以選擇任意app作為主app,但最好選擇那個存活時間最長的app。
在主app的AndroidManifest.xml中加入下面的service:
<service android:name="xiaofei.library.hermes.HermesService$HermesService0"/>
你可以加上一些屬性。在app間收發的事件類必須有相同的包名、相同的類名和相同的方法。務必記住在代碼混淆的時候將這些類keep!
然后在主app的application類的onCreate方法中加入:
HermesEventBus.getDefault().init(this);
其他app的Application類的onCreate方法中加入:
HermesEventBus.getDefault().connectApp(this, packageName);
“packageName”指的是主app的包名。
同上一樣,在每次使用EventBus的時候,用HermesEventBus代替EventBus。
HermesEventBus.getDefault().register(this); HermesEventBus.getDefault().post(new Event());
HermesEventBus也能夠在一個進程間傳遞event,所以如果你已經使用了HermesEventBus,那么就不要再使用EventBus了。
如果進程不需要再發送和接受event,那么這個進程必須調用:
HermesEventBus.getDefault().destroy();
否則你會收到android.os.DeadObjectException
和其他一些異常。這些異常會打印一些異常信息但不會導致app崩潰。
參考:https://github.com/Xiaofei-it/HermesEventBus/blob/master/README-zh-CN.md
至此HermesEventBus的基本使用就夠了,但是學習知識,我們必須要知其然,知其所以然。因為這個項目目前也是很久沒維護了,如果我們想嘗試商用,還是需要了解其原理並在以后能夠盡量維護和完善這套框架的。
四、HermesEventBus 的原理
在Application中進行了初始化操作:
HermesEventBus.getDefault().init(this);
當主進程和子進程創建的時候,都會執行此方法,在init方法內部,對主進程和子進程的初始化調用分別執行了不同的邏輯:
public void init(Context context) { mContext = context.getApplicationContext(); mMainProcess = isMainProcess(context.getApplicationContext()); if (mMainProcess) { Hermes.init(context); Hermes.register(MainService.class); mMainApis = MainService.getInstance(); Log.e(GlobalConfig.Log_TAG, "Main ProcessInit"); } else { mState = STATE_CONNECTING; Hermes.setHermesListener(new HermesListener()); Hermes.connect(context, Service.class); Hermes.register(SubService.class); Log.e(GlobalConfig.Log_TAG, "Child ProcessInit"); } }
五、Hermes 進階整理
Hermes 手寫實現核心邏輯:https://gitee.com/renhui112115/hermes-event-bus
附(優秀開源IPC框架) :
Hermes : https://github.com/Xiaofei-it/Hermes:Hermes的原理是利用動態代理+反射的方式來替換AIDL生成的靜態代理。
Andromeda:https://github.com/iqiyi/Andromeda。愛奇藝開源的IPC框架,加入了跨進程通信的事件總線,加入了對增強進程穩定性的考量,通過為各個進程預先插樁Service,在獲取遠程服務時用前台UI組件(Activity/Fragment/View)綁定插樁的Service,最終提升后台服務進程優先級。支持IPCCallback。支持配置Binder分發管理中心(Dispatcher)所屬進程。【2021年1月補充:Andromeda 框架現階段存在Gradle插件使用問題:Caused by: groovy.lang.MissingPropertyException: No such property: absolutePath for class: org.gradle.api.internal.file.DefaultFilePropertyFactory$DefaultDirectoryVar。 有時間的可以進行學習了解,擴寬自己的思路,實際生產環境使用不推薦。】