EventBus:
由开源组织greenrobot开发的事件发布-订阅总线库。
设计模式:
软件开发中问题的解决套路。
策略模式简介
定义:策略模式定义了一系列封装好的可以相互替换的算法
策略模式让算法独立于使用它的客户而独立变化。将可以互相替换的算法封装成一个一个的类,任意地替换。从而降低if...else 所带来的复杂和难以维护。
若源代码中有Strategy这个词,大概率使用了策略模式。
EventBus线程中的策略模式
EventBus定义了四种线程模式,直接上枚举ThreadMode的源码:
// 每个事件处理程序方法都有一个线程模式,该模式确定EventBus将在哪个线程中调用该方法。
// EventBus独立于发布线程来处理线程。
public enum ThreadMode {
PostThread,
MainThread,
BackgroundThread,
Async
}
四种线程模式含义如下:
ThreadMode.POSTING —— POST线程,订阅方法运行在发布者所在的线程(默认)
ThreadMode.MAIN —— UI主线程,订阅方法运行在主线程
ThreadMode.BACKGROUND —— 后台线程,发布者是主线程,订阅方法运行在新开子线程;发布者是子线程,订阅方法运行在发布者所在的线程;
ThreadMode.ASYNC —— 异步线程,订阅方法运行在新开子线程,无论发布者是在哪个线程
那这4中线程模式在哪里用到了呢?我们继续追溯源码:
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case PostThread:
invokeSubscriber(subscription, event);
break;
case MainThread:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BackgroundThread:
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case Async:
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
此段代码用switch做了线程模式的判断,其中主要调用invokeSubscriber()方法和xxxxxPoster.enqueue()方法。先来看一下invokeSubscriber()函数。先不讲这两个函数,跳回到策略模式,EventBus类中定义了3个Poster策略:
private final HandlerPoster mainThreadPoster; // 主线程Poster
private final BackgroundPoster backgroundPoster; // 后台线程Poster
private final AsyncPoster asyncPoster; // 异步线程Poster
这三个类:
HandlerPoster extends Handler // 主线程中直接调用Handler
AsyncPoster implements Runnable // Runnable是最常用的线程接口
BackgroundPoster implements Runnable
然后分别讲解一下invokeSubscriber()方法。首先上invokeSubscriber()的源码:
/*
如果订阅存活,调用订阅者。
跳过订阅以防止注销和事件传递之间的竞争。
否则注销的事件依然会被传递。
这对于一个活动或片段的生存周期至关重要。
*/
void invokeSubscriber(PendingPost pendingPost) {
Object event = pendingPost.event;
Subscription subscription = pendingPost.subscription;
PendingPost.releasePendingPost(pendingPost);
if (subscription.active) { // 若存活才invoke
invokeSubscriber(subscription, event);
}
}
void invokeSubscriber(Subscription subscription, Object event) {
try { // 此处的method用到了反射
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}
参考文献
1、设计模式|菜鸟教程:https://www.runoob.com/design-pattern/design-pattern-tutorial.html
2、《Android源码设计模式解析与实战》何红辉,关爱民著
3、蕉下孤客:https://www.jianshu.com/p/1b68ace4600a
4、野生的安卓兽:https://www.jianshu.com/nb/10598547
网友评论