美文网首页
EventBus设计模式剖析(五)策略模式

EventBus设计模式剖析(五)策略模式

作者: YongtaoHuang | 来源:发表于2019-07-21 17:30 被阅读0次

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

下一篇 EventBus设计模式剖析(二)建造者模式

All is well.

相关文章

网友评论

      本文标题:EventBus设计模式剖析(五)策略模式

      本文链接:https://www.haomeiwen.com/subject/gfxvlctx.html