分析一個(gè)開源項(xiàng)目的源碼铆帽,首先先從使用的入口開始氯檐,然后Debug或者點(diǎn)點(diǎn)點(diǎn)即可蜕窿。很多時(shí)候源碼并不難, 只是被很多人分析難了氮采,就像我有時(shí)候?qū)憱|西僅僅令自己看一樣殷绍,有時(shí)候只是寫代碼片段,所以最好的學(xué)習(xí)方式還是直接看源碼鹊漠。
EventBus的源碼很簡單主到,總結(jié)一下,能夠在不同組件Activity等等通信的原理即 一個(gè)static的單例對象躯概,成員變量是一個(gè)List等容器==>
注冊時(shí) 用來存放觀察者(List.add)
發(fā)送時(shí) 用來通知觀察者
List list = EventBus靜態(tài)對象.getList();
for(Object o:list){
EventBus靜態(tài)對象.notify(o);
}
總之登钥,能夠通信就是因?yàn)檫@個(gè)static的對象在自己調(diào)用自己的方法或成員等等.....
**下面是EventBus的用法和原理詳解 **
對于代碼能力理解比較好的可以直接看源碼,當(dāng)然這里也要一個(gè)我改寫過的EventBus版本娶靡,針對原有版本做了簡化牧牢,去除了注解方式,因?yàn)槲腋杏X注解完全是多余的一項(xiàng)姿锭,僅僅使用方便了一些而已塔鳍,卻帶來了理解上的難度和效率的低下
項(xiàng)目地址 https://github.com/wangli0/EventBus
其中tag v0.1是最原始的觀察者模式,此庫完全可以替代原有的EventBus
EventBus用法
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
}
public void onclick(View view) {
Intent intent = new Intent();
intent.setClass(this, TwoActivity.class);
startActivity(intent);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
EventBus.getDefault().post(111);
}
},3000);
}
}
public class TwoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
EventBus.getDefault().register(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void helloEventBus(Integer message) { //方法名任意呻此,這里的參數(shù)和 EventBus.getDefault().post(111);對應(yīng)即可
System.out.println("------>"+message);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
總結(jié): EventBus既可以在一個(gè)Activity里面使用轮纫,又可以在兩個(gè)Activity中使用,不管當(dāng)前顯示的是哪個(gè)焚鲜,只要Activity存在掌唾,消息就會發(fā)送成功。好比 EventBus.getDefault().register(this);就是一個(gè)BroadCastReceiver
原理分析
public final class EventType {
/**
* 默認(rèn)的tag
*/
public static final String DEFAULT_TAG = "default_tag";
/**
* 參數(shù)類型 即用 @Subscriber標(biāo)注的方法中的方法參數(shù)
*/
Class<?> paramClass;
/**
* 函數(shù)的tag
*/
public String tag = DEFAULT_TAG;
public Object event ;
}
EventBus.getDefault().register(this);執(zhí)行流程
EventBus中維護(hù)一個(gè) mMethodHunter對象忿磅,該對象用來查找this即Subscriber的所有標(biāo)有注解的所有方法
SubsciberMethodHunter和EventBus中 的 mSubcriberMap是同一個(gè)對象 糯彬。鍵值對是 key: EventType value:CopyOnWriteArrayList(Subscription)用于保存一個(gè)EventType類型對應(yīng)多個(gè)Subscription,方便EventBus post()時(shí)候能根據(jù)一個(gè) EventType類型葱她,查找該類型對應(yīng)的所有Subscription情连,然后全部執(zhí)行。
注意: Subscription是不區(qū)分觀察者是誰(這句話得意思是,一個(gè)Activity對象中可能有多個(gè)Subscription,另一個(gè)Activity也有多個(gè),但是他們不區(qū)分)览效,即它只根據(jù)EventType去查找所有Subscription
當(dāng)mMethodHunter查找到register(this) 中this類標(biāo)注@Subscriber 的所有方法后却舀,每一個(gè)符合要求的方法都 構(gòu)造一個(gè)EventType類,如下
EventType eventType = new EventType(paramType, annotation.tag());
//paramType是訂閱方法的唯一的參數(shù)
然后锤灿,根據(jù)subscriber對象即this和Method 構(gòu)造一個(gè)Subscription對象
Subscription newSubscription = new Subscription(subscriber, method);
然后從根據(jù)EventType從 mSubcriberMap中 獲取CopyOnWriteArrayList 挽拔,然后放進(jìn)去(把同類型的事件對應(yīng)->多個(gè)Subscription,如果list還不存在但校,new一個(gè))
注意: 從這里可以看出螃诅,this中可能有多個(gè)@Subscriber注解,那么就會構(gòu)造多個(gè)Subscription對象状囱。且每個(gè)Subscription里面都有一個(gè)真正的subscriper即this
真正執(zhí)行方法的時(shí)候 => 調(diào)用的是Subscription中method成員變量术裸,反射實(shí)現(xiàn)
subscription.targetMethod.invoke(subscription.subscriber.get(), event);
EventBus.getDefault().post事件
EventBus中另一個(gè)比較有意思的成員變量對象就是 Queue了
ThreadLocal<Queue<EventType>> mLocalEvents = new ThreadLocal<Queue<EventType>>() {
protected Queue<EventType> initialValue() {
return new ConcurrentLinkedQueue<EventType>();
};
};
查看 post方法
public void post(Object event, String tag) {
mLocalEvents.get().offer(new EventType(event.getClass(), tag));
mDispatcher.dispatchEvents(event);
}
看到這里,發(fā)現(xiàn)EventBus這個(gè)地方的思路和AsynTask有點(diǎn)相似呢亭枷!
獲取Queue然后把當(dāng)前的要發(fā)送的new EventType(event.getClass(), tag)類型放入隊(duì)列中袭艺。
然后獲取事件分發(fā)器分發(fā)事件:
mDispatcher.dispatchEvents(event);
void dispatchEvents(Object aEvent) {
Queue<EventType> eventsQueue = mLocalEvents.get();
while (eventsQueue.size() > 0) { //把Queue中的事件全部發(fā)出去
deliveryEvent(eventsQueue.poll(), aEvent);
}
}
void deliveryEvent(EventType type, Object aEvent) {
// 如果有緩存則直接從緩存中取
List<EventType> eventTypes = getMatchedEventTypes(type, aEvent);
// 迭代所有匹配的事件并且分發(fā)給訂閱者
for (EventType eventType : eventTypes) {
handleEvent(eventType, aEvent);
}
}
根據(jù)EventType獲取list即 List<Subscription> subscriptions = mSubcriberMap.get(eventType);
然后for循環(huán)執(zhí)行所有 Subscription
/**
* 處理單個(gè)事件
*
* @param eventType
* @param aEvent
*/
private void handleEvent(EventType eventType, Object aEvent) {
List<Subscription> subscriptions = mSubcriberMap.get(eventType);
if (subscriptions == null) {
return;
}
for (Subscription subscription : subscriptions) {
final ThreadMode mode = subscription.threadMode;
EventHandler eventHandler = getEventHandler(mode);
// 處理事件
eventHandler.handleEvent(subscription, aEvent);
}
}
執(zhí)行方法,實(shí)質(zhì)即為調(diào)用反射Method.invoke();
subscription.targetMethod.invoke(subscription.subscriber.get(), event);