最近這幾天經常在空閒時間看到了AOP編程,其實也就是對面向事件過程編程,一開始一直很難理解這個名次。不過看到Android正好有面向事件編程,程序解藕的開源庫(Otto,EventBus)。所以閒暇時間就去看了一下這兩個庫的源碼,寫篇博客記錄一下。其實很多時候,沉下心去做一件事就好了,收穫會伴隨着的。
用法
首先從用法上面來說,兩個框架的用法本質上其實是差不多的:註冊(register),發佈事件(post),接收事件(onEvent…),事件類,取消註冊(unregister)。兩個框架都包含這幾樣東西。另外Otto有個不同點是Otto有個Produce,生成事件的函數。它們的事件都包含sticky事件。下面分別介紹兩個簡單的使用API。
Otto
public class TestActivity extends Activity{
public static class TestEvent{
}
public void onCreate(Bundle b){
/*...*/
final Bus bus = new Bus();
bus.register(this)
findViewById(R.id.testpost).setOnClickListener(new View.OnClickListener(){
public void onClick(View view){
bus.post(new TestEvent()); //發佈事件,消息
}
}
}
@Subscribe public void onTestEvent(TestEvent event){
// TODO process the event.響應TestEvent發出的時候,@Subscribe註釋標記訂閱。
}
@Produce public TestEvent produceAnswer(){
// Produce 表示產生事件
return new TestEvent();
}
}
EventBus
public class TestActivity extends Activity{
public static class TestEvent{
}
public void onCreate(Bundle b){
/*...*/
final EventBus bus = EventBus.getDefault();
bus.register(this);
findViewById(R.id.testpost).setOnClickListener(new View.OnClickListener(){
public void onClick(View view){
bus.post(new TestEvent()); //發佈事件,消息
}
}
}
public void onEvent(TestEvent event){
// 以onEvent開頭就是接受事件,訂閱
}
}
上面僅僅是範例性的展示,除了這個簡單的使用外,在Android比較關鍵的就是UI線程跟普通的線程。Otto會將處理的線程跟發送的線程保持一致,你也可以自己設置線程,Bus提供了一個那樣的參數。而EventBus則可以自己指定線程,有四種方式,可以在onEvent後面加個後綴。比如:onEventMainThread。
另外一方面,EventBus也是提供了一個默認的單例EventBus(EventBus.getDefault())。我覺得這樣能夠更加方便地在Activity和Activity,Activity和Fragment解藕。
框架流程
本身這兩個框架都不是很大,其核心代碼都在接口類裏面(Bus,EventBus)。這裏就用流程的方式表示其具體結構。
Otto的框架流程
EventBus流程
需要特別指出的是。
1. Otto的訂閱者運行的線程跟跟發送的線程是一致的,但是EventBus的會根據用戶聲明訂閱的函數的時候指定的線程來去運行。
2. Otto只會查找當前類中的訂閱者,跟Produce。但是EventBus會查找父類的訂閱者。在post的時候,兩個框架都會去查找Event的父類型,畢竟Event也是屬於它的父類型類型。
3. 兩個框架都採用了很多緩存,比如查找訂閱者的時候。事件與對應的訂閱者也是緩存着的。
個人看法
如果從源碼上來看,兩個框架都是比較簡單的框架,代碼量都比較小。使用起來的話,我覺得EventBus會更加適用一點。但是Otto更加簡潔。
這兩個框架通過事件驅動來將Activity,Fragment解藕。但是如果在一個Activity內部使用的話,我覺得效果可能不是很好,這個框架目的在於Android組件之間的解藕。
另外兩種框架都是使用了一種先解析將訂閱者緩存起來,提高查找速度。這個策略在其他的框架中也是使用的非常多。