zoukankan      html  css  js  c++  java
  • 事件总线模式

    经过对多个有关事件总线模式的文档介绍的阅读,对事件总线模式有了一定的了解,并作出如下总结:

      事件总线模式主要是处理事件,包括4个主要组件:事件源、事件监听器、通道和事件总线。消息源将消息发布到事件总线上的特定通道上。侦听器订阅特定的通道。侦听器会被通知消息,这些消息被发布到它们之前订阅的一个通道上。

    使用场景:安卓开发、通知服务

    优点:新的发布者、订阅者和连接可以很容易地添加。对高度分布式的应用程序有效。

    缺点:可伸缩性可能是一个问题,因为所有消息都是通过同一事件总线进行的。

    事件总线的处理流程:

      

      实例:事件总线模式是一种广泛运用于安卓开发之中的一种软件架构模式,而事件总线模式在安卓开发中最广泛的应用莫过于AndroidStudio提供的EventBus,所以我就EventBus来谈谈对事件总线模式的认识。

      EventBus是Android下高效的发布/订阅事件总线机制。作用是可以代替传统的Intent,Handler,Broadcast或接口函数在Fragment,Activity,Service,线程之间传递数据,执行方法。特点是代码简洁,是一种发布订阅设计模式(Publish/Subsribe),或称作观察者设计模式。我们可能对事物总线机制还是有点陌生,但是想必对23种软件设计模式之后的观察者模式应该很熟悉。事物总线模式就是观察者设计模式的一种,它的工作部件主要分为四种:事件源、事件监听器、通道和事件总线。它的主要工作原理:事件源将产生的消息发送到事件总线的特定通道之上,然后监听器在事先会订阅事务总线之中不同的通道以区分消息的响应,然后当消息被发送到事务总线的特定通道之中时,所对应的监听器会监听到消息,然后监听器根据程序中设置的响应函数进行执行。就好像一个Activity之中设置的Button一样,在xml文件中放入一个Button,然后在java类中设定OnEvent()函数,当Button被点击的时候,则会传出一个点击消息,然后按钮对应的Onclick()函数,监听到点击消息,从而执行OnListerner()之中的函数。

      那么下面我们结合具体的实例来分析事件总线模式,提到这个模式我们第一个想到的一定是Adroid开发之中的一个组件——Event Bus。Event Bus是Android Studio官方为我们提供的一个工具包。下面我们就根据一个具体的框架来对Event Bus进行讲解。

      我们想要实现的一个效果是,有两个acivity如图MainActivity:当点击"click"按钮的时候,就会跳转到secondActivity,而secondActivity里面有两个按钮,点击以后,可以改变MainActivity里面TextView的文字。

      要实现这样的效果无非是完成一个消息的传递,相当于我们的观察者模式中发布者发布的一个消息,然后订阅者通过特定的通道进行监听,最后实现消息的传递。

     首先是MainActivity:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class MainActivity extends FragmentActivity { 
       
        Button btn; 
        TextView text; 
        @Override 
        protected void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.activity_main); 
            EventBus.getInstance().register(this); 
            btn = (Button) findViewById(R.id.btn); 
            text = (TextView) findViewById(R.id.text); 
            btn.setOnClickListener(new View.OnClickListener() { 
                @Override 
                public void onClick(View v) { 
                    startActivity(new Intent(MainActivity.this,SecondActivity.class)); 
                
            }); 
        
       
        public void onEvent(Info i){ 
            Log.i("cky", i.msg); 
        
       
        public void onEventMain(Info i){ 
            text.setText(i.msg); 
        
       
        public void onEventMain(Info2 i){ 
            text.setText(text.getText()+i.msg); 
        
    }

      从上面我们可以看出MainActivity的创建函数onCreate函数中调用了EventBus的register(this)函数,用来注册。然后是onEvent(),这个方法里面的代码,会在一个子线程中执行一个是onEventMain(),这个方法里面的代码,会在UI线程执行。

      然后是SecondActivity

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class SecondActivity extends Activity { 
       
        Button btn2; 
        Button btn3; 
        @Override 
        protected void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.activity_second); 
            btn2 = (Button) findViewById(R.id.btn2); 
            btn2.setOnClickListener(new View.OnClickListener() { 
                @Override 
                public void onClick(View v) { 
                    EventBus.getInstance().post(new Info("信息1")); 
                
            }); 
            btn3 = (Button) findViewById(R.id.btn3); 
            btn3.setOnClickListener(new View.OnClickListener() { 
                @Override 
                public void onClick(View v) { 
                    EventBus.getInstance().post(new Info2("信息2")); 
                
            }); 
        
    }

      那么这些活动之中的“始作俑者”——EventBus类又是什么样的呢?

      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class EventBus { 
        HashMap<Class<?>,ArrayList<Subscription>> subscriptionsByEventType = 
                new HashMap<Class<?>,ArrayList<Subscription>>(); 
        MainThreadHandler mainThreadHandler = new MainThreadHandler(this,Looper.getMainLooper()); 
        AsyThreadHandler asyThreadHandler = new AsyThreadHandler(this); 
       
        private final static EventBus instance = new EventBus(); 
        public static EventBus getInstance(){ 
               return instance; 
        
        private EventBus(){}; 
    }

      在这其中:

      register方法之中我们先获取了订阅者(例子中是MainActivity)的方法,找到onEvent开头的方法,获得它们的参数类型。然后判断subscriptionsByEventType是否有以这些参数类型为key的数据,如果没有,新建一个ArrayList<Subscription>。

      Subscription它代表一个订阅,拥有subsriber,也就是订阅者还有一个SubscriberMethod,这是订阅方法类。

      post()方法里面,如同我们上面所说,获取了参数类型,然后在subscriptionsByEventType中查询所有改类型对应的订阅Subscription对于Subscription,它有我们订阅类的所有信息。首先根据type判断是在主线程还是子线程执行,然后调用一开始讲到的两个类的实例就好了。

      invoke()其实只有一句话,就是调用了反射去执行方法。m是订阅方法,sub.subscriber就是订阅者,event就是post()方法传入的实体这样我们就在子线程中调用了这个方法了,相当于MainActivity主动调用这个方法。

      因为这个模式的使用较少所以网上可以找到的只有这一种实例,其实事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉。事件总线是对发布-订阅模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的。

    http://www.cnblogs.com/sheng-jie/p/6970091.html这里是一个相关案例,如果大家看完本文还是不能理解可以去看一下。

  • 相关阅读:
    2016第41周二
    2016第41周一
    2016第40周日
    svn冲突
    海量数据搜索
    网页爬虫的设计与实现(Java版)
    Eclipse中使用正则表达式搜索替换
    nodpad++正则替换
    DWR3.0 dwr 返回值(数组,集合,Map)
    自己用反射写的一个request.getParameter工具类
  • 原文地址:https://www.cnblogs.com/xhxdeblog/p/9099138.html
Copyright © 2011-2022 走看看