美文网首页
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