經(jīng)過(guò)對(duì)多個(gè)有關(guān)事件總線模式的文檔介紹的閱讀,對(duì)事件總線模式有了一定的了解,并作出如下總結(jié):
事件總線模式主要是處理事件,包括4個(gè)主要組件:事件源、事件監(jiān)聽(tīng)器、通道和事件總線。消息源將消息發(fā)布到事件總線上的特定通道上。偵聽(tīng)器訂閱特定的通道。偵聽(tīng)器會(huì)被通知消息,這些消息被發(fā)布到它們之前訂閱的一個(gè)通道上。
使用場(chǎng)景:安卓開(kāi)發(fā)、通知服務(wù)
優(yōu)點(diǎn):新的發(fā)布者、訂閱者和連接可以很容易地添加。對(duì)高度分布式的應(yīng)用程序有效。
缺點(diǎn):可伸縮性可能是一個(gè)問(wèn)題,因?yàn)樗邢⒍际峭ㄟ^(guò)同一事件總線進(jìn)行的。
事件總線的處理流程:
實(shí)例:事件總線模式是一種廣泛運(yùn)用于安卓開(kāi)發(fā)之中的一種軟件架構(gòu)模式,而事件總線模式在安卓開(kāi)發(fā)中最廣泛的應(yīng)用莫過(guò)于AndroidStudio提供的EventBus,所以我就EventBus來(lái)談?wù)剬?duì)事件總線模式的認(rèn)識(shí)。
EventBus是Android下高效的發(fā)布/訂閱事件總線機(jī)制。作用是可以代替?zhèn)鹘y(tǒng)的Intent,Handler,Broadcast或接口函數(shù)在Fragment,Activity,Service,線程之間傳遞數(shù)據(jù),執(zhí)行方法。特點(diǎn)是代碼簡(jiǎn)潔,是一種發(fā)布訂閱設(shè)計(jì)模式(Publish/Subsribe),或稱(chēng)作觀察者設(shè)計(jì)模式。我們可能對(duì)事物總線機(jī)制還是有點(diǎn)陌生,但是想必對(duì)23種軟件設(shè)計(jì)模式之后的觀察者模式應(yīng)該很熟悉。事物總線模式就是觀察者設(shè)計(jì)模式的一種,它的工作部件主要分為四種:事件源、事件監(jiān)聽(tīng)器、通道和事件總線。它的主要工作原理:事件源將產(chǎn)生的消息發(fā)送到事件總線的特定通道之上,然后監(jiān)聽(tīng)器在事先會(huì)訂閱事務(wù)總線之中不同的通道以區(qū)分消息的響應(yīng),然后當(dāng)消息被發(fā)送到事務(wù)總線的特定通道之中時(shí),所對(duì)應(yīng)的監(jiān)聽(tīng)器會(huì)監(jiān)聽(tīng)到消息,然后監(jiān)聽(tīng)器根據(jù)程序中設(shè)置的響應(yīng)函數(shù)進(jìn)行執(zhí)行。就好像一個(gè)Activity之中設(shè)置的Button一樣,在xml文件中放入一個(gè)Button,然后在java類(lèi)中設(shè)定OnEvent()函數(shù),當(dāng)Button被點(diǎn)擊的時(shí)候,則會(huì)傳出一個(gè)點(diǎn)擊消息,然后按鈕對(duì)應(yīng)的Onclick()函數(shù),監(jiān)聽(tīng)到點(diǎn)擊消息,從而執(zhí)行OnListerner()之中的函數(shù)。
那么下面我們結(jié)合具體的實(shí)例來(lái)分析事件總線模式,提到這個(gè)模式我們第一個(gè)想到的一定是Adroid開(kāi)發(fā)之中的一個(gè)組件——Event Bus。Event Bus是Android Studio官方為我們提供的一個(gè)工具包。下面我們就根據(jù)一個(gè)具體的框架來(lái)對(duì)Event Bus進(jìn)行講解。
我們想要實(shí)現(xiàn)的一個(gè)效果是,有兩個(gè)acivity如圖MainActivity:當(dāng)點(diǎn)擊"click"按鈕的時(shí)候,就會(huì)跳轉(zhuǎn)到secondActivity,而secondActivity里面有兩個(gè)按鈕,點(diǎn)擊以后,可以改變MainActivity里面TextView的文字。
要實(shí)現(xiàn)這樣的效果無(wú)非是完成一個(gè)消息的傳遞,相當(dāng)于我們的觀察者模式中發(fā)布者發(fā)布的一個(gè)消息,然后訂閱者通過(guò)特定的通道進(jìn)行監(jiān)聽(tīng),最后實(shí)現(xiàn)消息的傳遞。
首先是MainActivity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public?class?MainActivity?extends?FragmentActivity {? ????Button btn;? ????TextView text;? ????@Override ????protected?void?onCreate(Bundle savedInstanceState) {? ????????super.onCreate(savedInstanceState);? ????????setContentView(R.layout.activity_main);? ????????EventBus.getInstance().register(this);? ????????btn = (Button) findViewById(R.id.btn);? ????????text = (TextView) findViewById(R.id.text);? ????????btn.setOnClickListener(new?View.OnClickListener() {? ????????????@Override ????????????public?void?onClick(View v) {? ????????????????startActivity(new?Intent(MainActivity.this,SecondActivity.class));? ????????????}? ????????});? ????}? ????public?void?onEvent(Info i){? ????????Log.i("cky", i.msg);? ????}? ????public?void?onEventMain(Info i){? ????????text.setText(i.msg);? ????}? ????public?void?onEventMain(Info2 i){? ????????text.setText(text.getText()+i.msg);? ????}? } |
從上面我們可以看出MainActivity的創(chuàng)建函數(shù)onCreate函數(shù)中調(diào)用了EventBus的register(this)函數(shù),用來(lái)注冊(cè)。然后是onEvent(),這個(gè)方法里面的代碼,會(huì)在一個(gè)子線程中執(zhí)行一個(gè)是onEventMain(),這個(gè)方法里面的代碼,會(huì)在UI線程執(zhí)行。
然后是SecondActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public?class?SecondActivity?extends?Activity {? ????Button btn2;? ????Button btn3;? ????@Override ????protected?void?onCreate(Bundle savedInstanceState) {? ????????super.onCreate(savedInstanceState);? ????????setContentView(R.layout.activity_second);? ????????btn2 = (Button) findViewById(R.id.btn2);? ????????btn2.setOnClickListener(new?View.OnClickListener() {? ????????????@Override ????????????public?void?onClick(View v) {? ????????????????EventBus.getInstance().post(new?Info("信息1"));? ????????????}? ????????});? ????????btn3 = (Button) findViewById(R.id.btn3);? ????????btn3.setOnClickListener(new?View.OnClickListener() {? ????????????@Override ????????????public?void?onClick(View v) {? ????????????????EventBus.getInstance().post(new?Info2("信息2"));? ????????????}? ????????});? ????}? } |
那么這些活動(dòng)之中的“始作俑者”——EventBus類(lèi)又是什么樣的呢?
1 2 3 4 5 6 7 8 9 10 11 12 |
public?class?EventBus {? ????HashMap ????????????new?HashMap ????MainThreadHandler mainThreadHandler =?new?MainThreadHandler(this,Looper.getMainLooper());? ????AsyThreadHandler asyThreadHandler =?new?AsyThreadHandler(this);? ????private?final?static?EventBus instance =?new?EventBus();? ????public?static?EventBus getInstance(){? ???????????return?instance;? ????}? ????private?EventBus(){};? } |
在這其中:
register方法之中我們先獲取了訂閱者(例子中是MainActivity)的方法,找到onEvent開(kāi)頭的方法,獲得它們的參數(shù)類(lèi)型。然后判斷subscriptionsByEventType是否有以這些參數(shù)類(lèi)型為key的數(shù)據(jù),如果沒(méi)有,新建一個(gè)ArrayList
Subscription它代表一個(gè)訂閱,擁有subsriber,也就是訂閱者還有一個(gè)SubscriberMethod,這是訂閱方法類(lèi)。
post()方法里面,如同我們上面所說(shuō),獲取了參數(shù)類(lèi)型,然后在subscriptionsByEventType中查詢所有改類(lèi)型對(duì)應(yīng)的訂閱Subscription對(duì)于Subscription,它有我們訂閱類(lèi)的所有信息。首先根據(jù)type判斷是在主線程還是子線程執(zhí)行,然后調(diào)用一開(kāi)始講到的兩個(gè)類(lèi)的實(shí)例就好了。
invoke()其實(shí)只有一句話,就是調(diào)用了反射去執(zhí)行方法。m是訂閱方法,sub.subscriber就是訂閱者,event就是post()方法傳入的實(shí)體這樣我們就在子線程中調(diào)用了這個(gè)方法了,相當(dāng)于MainActivity主動(dòng)調(diào)用這個(gè)方法。
因?yàn)檫@個(gè)模式的使用較少所以網(wǎng)上可以找到的只有這一種實(shí)例,其實(shí)事件總線這個(gè)概念對(duì)你來(lái)說(shuō)可能很陌生,但提到觀察者(發(fā)布-訂閱)模式,你也許就很熟悉。事件總線是對(duì)發(fā)布-訂閱模式的一種實(shí)現(xiàn)。它是一種集中式事件處理機(jī)制,允許不同的組件之間進(jìn)行彼此通信而又不需要相互依賴,達(dá)到一種解耦的目的。
評(píng)論