美文网首页Oh My AndroidAndroid技术知识Android开发
Android 小话设计模式 之 从观察者到EventBus和R

Android 小话设计模式 之 从观察者到EventBus和R

作者: Ivor0057 | 来源:发表于2016-05-23 11:29 被阅读1142次

      设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。

    前言

    软件工程中的23种设计模式,相信大家耳熟能详,在大Java中完美适用,直接上图(自己画的):


    Design Pattern.png

      这里主要给大家介绍一下神奇且常见的观察者模式,及其引申出的一些强大用法:CallBack,EventBus,RxJava。

    观察者模式

    观察者模式(Observer)完美的将观察者和被观察的对象分离开,定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
      简单的来说,打个比方,就类似于狱警时时刻刻盯着犯人,犯人作出一点小动作,那么狱警便立马做出回应,反之则相安无事。在Android中的点击事件监听setOnClickListener( )便完成对接这一概念,即:观察者将自己注册到被观察对象中,被观察对象将观察者存放在一个容器里。被观察对象发生了某种变化时,从容器中得到所有注册过的观察者,将变化通知观察者从而达到一个时时监听的作用。
      观察者(Observer)模式,又叫做发布订阅(Publish/Subscribe)模式,下面给出一张经典的观察者模式的关系对应图,看完大致都明白了吧~


    Observer Pattern.png

    强大的应用之处

    观察者模式相信大家都有了一个了解,在Android中最基本的实现就是对点击事件的监听了,相信网上关于观察者与setOnClickListener( )的关系介绍有很多很多咯,这里介绍两种更高级的应用场景,看完你便会完美体会到其强大之处!


    Observer Relation.png
    • EventBus

    EventBus是Android下高效的发布/订阅事件总线机制。是基于JVM内部的数据传输系统,其核心对象为Event和EventHandler。作用是可以代替传统的Intent,Handler,Broadcast或接口函数在Fragment,Activity,Service,线程之间传递消息,优点是开销小,代码更优雅,以及将发送者和接收者解耦。
      看完概念是不是感觉强大的EventBus已经无所不能了!那么就从源码层面分析下其强大的原因:
      汗!在看源码之前还是先看一下用法吧:

    0、Prepare

      Gradle:
            compile 'org.greenrobot:eventbus:3.0.0'
      Maven:
            <dependency>
                  <groupId>org.greenrobot</groupId>
                  <artifactId>eventbus</artifactId>
                  <version>3.0.0</version>
            </dependency>
    

    1、定义关系:写一个类描述被观察者和观察者之间统一事件关系,可以为空,也可以加上参数并通过get/set方法绑定。

      public class Event { 
            public Event() {
                  // TODO
            } 
      }
    

    2、接收事件页面:注册与销毁。

      @Override  
      protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            // 注册EventBus  
            EventBus.getDefault().register(this);  
      }
    
      // TODO
    
      @Override  
      protected void onDestroy(){  
            super.onDestroy();  
            // 销毁EventBus  
            EventBus.getDefault().unregister(this);
      }  
    

    3、发布事件页面:将之前定义在事件关系的类发布。

      EventBus.getDefault().post(new Event());
    

    4、接收事件页面:重写onEvent...( )方法,通过注解的方法鉴别类型,接收消息(4种方式)。

      @Subscribe(threadMode = ThreadMode.MainThread) 
      //在ui线程执行 
      public void onEvent(Event event) { 
              // TODO
      }
    
      @Subscribe(threadMode = ThreadMode.BackgroundThread) 
      //在后台线程执行 
      public void onEvent(Event event) { 
            // TODO
      }
    
      @Subscribe(threadMode = ThreadMode.Async) 
      //强制在后台执行 
      public void onEvent(Event event) { 
            // TODO
      }
    
      @Subscribe(threadMode = ThreadMode.PostThread) 
      //默认方式, 在发送线程执行 
      public void onEvent(Event event) { 
            // TODO
      }
    

    综上,一个Event就对应一个关系,在发布与接收者之间通过该标识的Event就可以自动识别作出响应。参考一下3.0之前在接收页面的接收方法,对应上面的(注:在EventBus3.0已经将原有的方法改版):

       - onEventMainThread():
            不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行。
            在Android中只能在UI线程中更新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。
    
      - onEventBackgroundThread():
            如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行。
            如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。
    
      - onEventAsync():
            无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync()。
    
      - onEvent():
            发布事件和接收事件线程在同一个线程。
            使用这个方法时,在onEvent方法中不能执行耗时操作。
            如果执行耗时操作容易导致事件分发延迟。
    

    下面简单分析一下源码,参考了鸿洋大神的帖子,从register( )方法入手,先看getDefault( ):

      /** Convenience singleton for apps using a process-wide EventBus instance. */
      public static EventBus getDefault() {
            if (defaultInstance == null) {
                  synchronized (EventBus.class) {
                        if (defaultInstance == null) {
                              defaultInstance = new EventBus();
                        }
                  }
            }
            return defaultInstance;
      }
    

    使用了双重判断的方式,防止并发的问题,还能极大的提高效率。再看一下普通的register( )方法:

      public void register(Object subscriber) {
            register(subscriber, DEFAULT_METHOD_NAME, false, 0);
      }
    
      public void register(Object subscriber, int priority) {
            register(subscriber, DEFAULT_METHOD_NAME, false, priority);
      }
    
      public void registerSticky(Object subscriber) {
            register(subscriber, DEFAULT_METHOD_NAME, true, 0);
      }
    
      public void registerSticky(Object subscriber, int priority) {
            register(subscriber, DEFAULT_METHOD_NAME, true, priority);
      }
    

    再点进去看看内部核心的register(subscriber...)方法:

      private synchronized void register(Object subscriber, String methodName, boolean sticky, int priority) {
            List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass(), methodName);
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                  subscribe(subscriber, subscriberMethod, sticky, priority);
            }
      }
    

    即遍历该类内部所有方法,然后根据methodName去匹配,匹配成功的封装成SubscriberMethod,最后返回一个List。继续深入的subscribe( )方法在这里就不贴代码了,有兴趣的童鞋可以自己无限往下点点看。
      register( )方法的核心便是:扫描了所有的方法,把匹配的方法最终保存在subscriptionsByEventType( )中,该方法中的eventType是我们方法参数的Class,Subscription中则保存着subscriber,subscriberMethod(method, threadMode, eventType),priority,包含了执行改方法所需的一切。
      其余的一些post( )方法等其实的本质与上方类似,关于整个EventBus的流程可以大致梳理如下:EventBus负责订阅对象与事件的管理,比如注册、注销以及发布事件等。在初始时将某个对象注册到EventBus中,EventBus会遍历该对象class中的所有方法,把参数数量为1且用了Subscriber注解标识的函数管理起来,以事件类型和订阅函数Subscriber的tag构建一个EventType作为一种事件类型,某个事件类型对应有一个接收者列表。当有事件发布时,EventBus会根据发布的事件类型与tag构建EventType,然后找到对应的订阅者列表,并且将这些事件投递给所有订阅者。SubscriberMethodHunter负责查找合适的EventType,而EventHandler则负责将这些订阅函数执行到相应的线程中。

    • RxJava

    Reactive Extensions编程简称Rx编程,又叫响应式编程,提供一致的编程接口,帮助开发者更方便的处理异步数据流,使软件开发更高效、更简洁。其中,对于异步错误处理,传统的try/catch没办法处理异步计算,Rx提供了合适的错误处理机制轻松使用并发。而Rx的Observables和Schedulers让开发者可以摆脱底层的线程同步和各种并发问题。
      关于RxJava的基本实现很简单,看如下三步:

    1、创建一个Observable对象,直接调用Observable.create( ):

      Observable<String> myObservable = Observable.create(
            new Observable.OnSubscribe<String>() {
                  @Override
                  public void call(Subscriber<? super String> sub) {
                        sub.onNext("Hello, world!");
                        sub.onCompleted();
                  }
            }
      );
    

    2、创建一个Subscriber来处理Observable对象发出的字符串:

      Subscriber<String> mySubscriber = new Subscriber<String>() {
            @Override
            public void onNext(String s) { 
                  System.out.println(s); 
            }
    
            @Override
            public void onCompleted() {
                  // TODO
            }
    
            @Override
            public void onError(Throwable e) {
                  // TODO
            }
      };
    

    3、通过subscribe函数就可以将myObservable对象和mySubscriber对象关联绑定起来,完成subscriber对observable的订阅:

      myObservable.subscribe(mySubscriber);
    

    当然,强大的RxJava提供了一些方法使代码简化,如just( ),map( ),Action1类等等,如:

      Observable.just("Hello, world!")
            .subscribe(new Action1<String>() {
                  @Override
                  public void call(String s) {
                        System.out.println(s);
                  }
            });
    
      Observable.just("Hello, world!")
            .map(new Func1<String, String>() {
                  @Override
                  public String call(String s) {
                        return s + "Ivor";
                  }
            }).subscribe(new Action1<String>() {
                  @Override
                  public void call(String s) {
                        System.out.println(s);
                  }
            });
    

    关于RxJava的基本使用大致就介绍到这里,后续关于RxJava和Retrofit以及RxAndroid的引申下期会更新,大家也可以提前参考一下福生宝宝的RxJava 的使用与理解(二)

    • EventBus VS RxJava

    RxJava要比EventBus的应用更广泛,EventBus仅仅是作为一种消息的传递工具,但是RxJava里面几乎可以做任何事情,只是对于简单的业务来说可能有些冗余,EventBus相对来说更加轻量,EventBus有个缺点就是凡是使用了EventBus的类都不能进行混淆了,否则Evnetbus就找不到OnEvent方法了。

    尾声

    关于观察者模式的应用有很多,这里先介绍这么两种强大的库,供大家参考学习~~请将强大的Observer与Listener发挥到极致:)

    相关文章

      网友评论

      本文标题:Android 小话设计模式 之 从观察者到EventBus和R

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