第三方開源庫 EventBus 原始碼分析和手寫

2021-10-12 01:31:17 字數 4716 閱讀 6533

eventbus官方介紹為乙個為android系統優化的事件訂閱匯流排,它不僅可以很方便的在同執行緒中傳遞事件或者物件,還可以在不同執行緒中實現事件或物件的傳遞,用法比較簡單,可以很好地完成一些在原生系統中的intent,handler等可以完成的工作,在android開發過程中用途及其廣泛。當然這裡不介紹它的具體用法,只走原始碼,然後自己動手寫一下加深印象。很多人都說用了觀察者設計模式,如果非得要往上靠,只能說不是正常的觀察者。當然我們也不用太關注,你就認為它是反射加註解。

我給別人寫的好幾個專案都用了這個開源庫,的確比較方便,可以減少很多不必要的**,但是也有某一些問題,就是可讀性並不是特別高,跨度有時還是比較大,當然我們可以採用規範來避免掉這些問題。

1.之前學到的一些設計模式:享元設計模式,單例設計模式,模板設計模式......

2.之前學到的一些基礎知識:volatile 關鍵字,執行緒間的通訊安全,執行緒池的運用......

3.反射和註解的一些細節,反射的快取,方法的修飾符,方法引數的反射......

4.能夠參考 eventbus 原始碼自己寫一些專案庫,像跨模組通訊框架......

#####1.eventbus.register()

public void register(object subscriber) }}

listfindsubscribermethods(class> subscriberclass)

// ignoregeneratedindex屬性表示是否忽略註解器生成的myeventbusindex。

// ignoregeneratedindex的預設值為false,可以通過eventbusbuilder來設定它的值

if (ignoregeneratedindex) else

if (subscribermethods.isempty()) else

}private listfindusingreflection(class> subscriberclass)

return getmethodsandrelease(findstate);

}private void findusingreflectioninsingleclass(findstate findstate) catch (throwable th)

// for 迴圈所有方法

for (method method : methods)

}} else if (strictmethodverification && method.isannotationpresent(subscribe.class))

} else if (strictmethodverification && method.isannotationpresent(subscribe.class)) }}

先看下 findsubscribermethods() 這個方法,會通過類物件的 class 去解析這個類中的所有 subscribe 註解方法的所有屬性值,乙個註解方法對應乙個 subscribermethod 物件,包括 threadmode,priority,sticky,eventtype,methodstring。該方法執行完畢之後應該是下面這張圖,效果就將就一下吧:

}// 處理優先順序

int size = subscriptions.size();

for (int i = 0; i <= size; i++)

}// 通過 subscriber 獲取 list>

list> subscribedevents = typesbysubscriber.get(subscriber);

if (subscribedevents == null)

// 將此事件類加入 訂閱者事件類列表中

subscribedevents.add(eventtype);

// 處理粘性事件

if (subscribermethod.sticky)

}} else }}

接下來看下 subscribe 這個方法,這個相對來說就簡單許多了,把 subscriber , subscribermethod 分別存好,到底怎麼存,這個時候看下面這兩個集合:

// subscriptionsbyeventtype 這個集合存放的是?

// key 是 event 引數的類

// value 存放的是 subscription 的集合列表

// subscription 包含兩個屬性,乙個是 subscriber 訂閱者(反射執行物件),乙個是 subscribermethod 註解方法的所有屬性引數值

private final map, copyonwritearraylist> subscriptionsbyeventtype;

// typesbysubscriber 這個集合存放的是?

// key 是所有的訂閱者

// value 是所有訂閱者裡面方法的引數的 class,eventtype

// 如果沒有訂閱者

if (!subscriptionfound)

if (sendnosubscriberevent && eventclass != nosubscriberevent.class &&

eventclass != subscriberexceptionevent.class) }}

private boolean postsingleeventforeventtype(object event, postingthreadstate postingstate, class> eventclass)

if (subscriptions != null && !subscriptions.isempty()) finally

// 如果被取消,則跳出迴圈

if (aborted)

}return true;

}return false;

}private void posttosubscription(subscription subscription, object event, boolean ismainthread) else

break;

// 子執行緒

case background:

if (ismainthread) else

break;

// 和傳送事件處於不同的執行緒

case async:

asyncposter.enqueue(subscription, event);

break;

default:

throw new illegalstateexception("unknown thread mode: " + subscription.subscribermethod.threadmode);}}

到這裡我們基本就把核心的內容解析完了,重點就是去遍歷 typesbysubscriber 找出滿足需求的然後反射執行對應的方法,至於在**執行這個就需要判斷 threadmode。

#####3.eventbus.unregister()

/** unregisters the given subscriber from all event classes. */

public synchronized void unregister(object subscriber)

// 將訂閱者從列表中移除

typesbysubscriber.remove(subscriber);

} else

}/** only updates subscriptionsbyeventtype, not typesbysubscriber! caller must update typesbysubscriber. */

private void unsubscribebyeventtype(object subscriber, class> eventtype) }}

}

第三方開源庫 CircleImageView

沒有對進行優化,若過大,容易oom,drawable a.jpg是大。dependencies邊框顏色 邊框寬度 circleimageview hdodenhof circleimageview circleimageview android layout width 180dp android ...

EventBus和Otto第三方

eventbus能夠簡化各元件間的通訊,讓我們的 書寫變得簡單,能有效的分離事件傳送方和接收方 也就是解耦的意思 event 事件。它可以是任意型別。subscriber 事件訂閱者。publisher 事件的發布者。我們可以在任意執行緒裡發布事件,一般情況下,使用eventbus.getdefau...

centos 第三方源

最後附上第三方源 centos由於很追求穩定性,所以官方源中自帶的軟體不多,因而需要一些第三方源,比如epel atrpms elrepo nux dextop repoforge等。epel epel即extra packages for enterprise linux,為centos提供了額外...