• 安卓开发笔记——探索EventBus


    1、关于EventBus:

    组件通讯在Android开发中是不可避免的,随着业务需求的复杂化,代码中需要我们去处理的业务逻辑难度也不断增大。例如多个Fragment之间的数据传递,Service与Activity、Fragment之间的通讯,BroadCast与Activity、Fragment之间的通讯,各种startActivityForResult的使用,繁杂的操作令我们所厌倦,在GitHub上找了下解决方案,发现了一个不错的开源库EventBus,相信很多做过Android开发的朋友都或多或少对此有所了解。

      EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。

      这是EventBus在GitHub上的开源库地址:https://github.com/greenrobot/EventBus

      EventBus的大体关系是这样的:订阅者(Subscriber)通过订阅事件(Event)到总线,事件发布者(Publisher)发布事件(Event)到总线被订阅者(Subscriber)接收,其实说白了就是软件设计模式里的观察者模式。EventBus在使用的时候就是在合适的地方发布一个事件,使得注册了该事件接收的对象就可以收到通知,进行相应的操作。

    2、初探EventBus:

      文绉绉的文字描述令人厌烦,直接上代码说话吧,先来看下要实现的效果:

      

      看似很简单的效果,点击按钮跳转界面,利用Intent发送一个消息,然后TextView接收显示。这是传统上的做法,如果真是这样做,那么写这篇文章的就完全没意义了。其实这里就是利用到了EventBus,并没有用到Intent来传递消息。

      先来看下具体的代码(记得添加EventBus的引用),然后我再分部来解析:

     1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
     2 
     3 import android.content.Intent;
     4 import android.os.Bundle;
     5 import android.support.v7.app.AppCompatActivity;
     6 import android.view.View;
     7 import android.widget.Button;
     8 import android.widget.TextView;
     9 
    10 import de.greenrobot.event.EventBus;
    11 
    12 public class MainActivity extends AppCompatActivity {
    13 
    14     private Button mBt_1;
    15     private TextView mTv_1;
    16 
    17     @Override
    18     protected void onCreate(Bundle savedInstanceState) {
    19         super.onCreate(savedInstanceState);
    20         setContentView(R.layout.activity_main);
    21         //注册绑定EventBus
    22         EventBus.getDefault().register(this);
    23 
    24         initView();
    25         initAction();
    26 
    27     }
    28 
    29     private void initAction() {
    30         mBt_1.setOnClickListener(new View.OnClickListener() {
    31             @Override
    32             public void onClick(View v) {
    33                 startActivity(new Intent(MainActivity.this, SecondActivity.class));
    34             }
    35         });
    36     }
    37 
    38     private void initView() {
    39         mBt_1 = (Button) findViewById(R.id.bt_1);
    40         mTv_1 = (TextView) findViewById(R.id.tv_info1);
    41     }
    42 
    43 
    44     //接收所订阅的消息
    45     public void onEventMainThread(MyEvent myEvent) {
    46         if (myEvent.getInfo()!=null) {
    47             mTv_1.setText(myEvent.getInfo());
    48         }
    49 
    50     }
    51 
    52 
    53     @Override
    54     protected void onDestroy() {
    55         super.onDestroy();
    56         //解绑EventBus
    57         EventBus.getDefault().unregister(this);
    58     }
    59 }
    MainActivity.java
     1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
     2 
     3 import android.os.Bundle;
     4 import android.support.v7.app.AppCompatActivity;
     5 import android.view.View;
     6 import android.widget.Button;
     7 import android.widget.Toast;
     8 
     9 import de.greenrobot.event.EventBus;
    10 
    11 public class SecondActivity extends AppCompatActivity {
    12 
    13     private Button mBt_2;
    14 
    15     @Override
    16     protected void onCreate(Bundle savedInstanceState) {
    17         super.onCreate(savedInstanceState);
    18         setContentView(R.layout.activity_second);
    19         initView();
    20         initAction();
    21 
    22     }
    23 
    24     private void initAction() {
    25         mBt_2.setOnClickListener(new View.OnClickListener() {
    26             @Override
    27             public void onClick(View v) {
    28                 Toast.makeText(SecondActivity.this,"消息已发送",Toast.LENGTH_SHORT).show();
    29                 EventBus.getDefault().post(new MyEvent("我是被发送过来的消息"));
    30 
    31             }
    32         });
    33     }
    34 
    35     private void initView() {
    36         mBt_2 = (Button) findViewById(R.id.bt_2);
    37     }
    38 
    39 
    40 }
    SecondActivity.java
     1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
     2 
     3 /**
     4  * Created by Lichenwei
     5  * Date: 2015-10-11
     6  * Time: 18:23
     7  */
     8 public class MyEvent {
     9 
    10     private String info;
    11 
    12     public MyEvent(String info) {
    13         this.info = info;
    14     }
    15 
    16     public String getInfo() {
    17         return info;
    18     }
    19 
    20     public void setInfo(String info) {
    21         this.info = info;
    22     }
    23 }
    MyEvent

      上面的代码很简单,这里只是抛砖引玉并不做太多复杂的操作,大家可以根据自己的项目需求来添加对应的代码。

    3、解析代码:

    1、注册EventBus: 

      在添加EventBus的引用后,我们就可以对任意类进行注册绑定和解绑EventBus事件,注册方法和反注册方法很简单,在上面的代码中就可以看出来了,分别是register和unregister,这里的EventBus.getDefault是获取到EventBus实例的意思(单例)。

    1 //注册绑定EventBus
    2 EventBus.getDefault().register(this);
    3 //解绑EventBus
    4 EventBus.getDefault().unregister(this);

    2、EventBus事件:

      EventBus很灵活,它对事件不进行任何的限制,也不需要继承或者实现任何类或者接口,可以是任意类型的实体类,好比上面代码提到的MyEvent。

    3、EventBus事件发布者:

      有了事件之后,我们就可以对事件进行发布,然后可以被订阅这个事件的所有订阅者所接收。发送事件很简单,有两种方法post与postSticky:

    1 //立即发送事件 
    2 EventBus.getDefault().post(Object event);
    3 //延迟发送事件
    4 EventBus.getDefault().postSticky(Objet event);

    4、EventBus事件订阅者:

      EventBus的事件订阅者可以是任何已经进行注册EventBus的类,订阅者的数量是没有上限的(很重要,下文会提到),这里的订阅有4种方法,这里都是由onEvent开头的,有着一定的区别:

      1、onEvent:

      如果使用onEvent作为订阅函数,那么该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。
      2、onEventMainThread:

      如果使用onEventMainThread作为订阅函数,那么不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。
      3、onEventBackground:

      如果使用onEventBackgrond作为订阅函数,那么如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。
      4、onEventAsync:

      使用这个函数作为订阅函数,那么无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync。

    1  public void onEvent(Object event) {}
    2  public void onEventMainThread(Object event) {}
    3  public void onEventBackgroundThread(Object event) {}
    4  public void onEventAsync(Object event) {}

      介绍完EventBus里的所有角色后,我们来理一理订阅/被订阅流程:

      首先,要想成为事件订阅者需要先对EventBus进行注册绑定,然后在本类需要去写一个以onEvent开头的方法来接收处理消息事件,再来我们需要一个自定义的事件可以让事件的发布者发布,让事件的订阅者接收。事件的发布可以通过post方法或者是postSticky方法发布。

    4、EventBus所带来的一些方便之处:

      EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。这是我们在文章开头所介绍过的,这里就不多说了,说几个在实际开发中所运用到的地方。

      例如:

      1、当某个页面的某些值发生变化的时候,需要去同时去更改多个页面相对应的值,这时候只要这些类注册订阅了该事件,那么我们就可以很轻松通过post发送消息来进行通讯。

      2、某些时候,我们并不希望发布出来的Event立即被消费掉,而是等到时机成熟。比如说,在一个详情页点赞之后,产生一个事件,这个事件并不立即被消费,而是等用户退出详情页回到商品列表之后,接收到该事件,然后刷新Adapter等。其实这就是之前我们用startActivityForResult和onActivityResult做的事情。这里我们就可以利用postSticky来实现这样的机制。

      总之,EventBus极大的减轻了我们各种组件之间的通讯复杂度,也大大减少了使用ActivityForResult的麻烦。真实值得极力推荐。

    5、理解EventBus

      从源码中我们可以知道,当我们在类中注册绑定EventBus的时候,它会去扫描当前类并记录下所有已onEvent开头的方法,存放在一个Map<Key,Value>中,在事件通过post发布之后,EventBus会根据post中实参的类型,去Map中查找对应的方法,并找到了对应的Thread,最终利用Java的反射机制去执行我们的方法。

      onEventMainThread表示这个方法会在UI主线程执行。

      onEventPostThread表示这个方法会在当前发布事件的线程中执行。

      BackgroundThread表示如果在非UI主线程发布的事件,则直接执行,和发布在同一个线程中。如果在UI线程发布的事件,则加入后台任务队列,使用线程池一个接一个调用。

      Async 加入后台任务队列,使用线程池调用,注意没有BackgroundThread中的一个接一个。

    作者:李晨玮
    出处:http://www.cnblogs.com/lichenwei/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
    正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

  • 相关阅读:
    [Voice communications] 声音的滤波
    [Voice communications] 声道的转换
    [Voice communications] 音量的控制
    [Voice communications] 看得到的音频流
    [Voice communications] 让音乐响起来
    HDFS之FileStatus
    HDFS中JAVA API的使用
    hadoop集群环境的搭建
    【ARM-Linux开发】【CUDA开发】【深度学习与神经网络】Jetson Tx2安装相关之三
    【ARM-Linux开发】【CUDA开发】【深度学习与神经网络】Jetson Tx2安装相关之三
  • 原文地址:https://www.cnblogs.com/lichenwei/p/4873249.html
Copyright © 2020-2023  润新知