zoukankan      html  css  js  c++  java
  • 安卓开发笔记——探索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/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
    正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 一元三次方程
    Java实现 蓝桥杯VIP 算法训练 乘法表
    Java实现 蓝桥杯VIP 算法训练 矩阵加法
    Java实现 蓝桥杯VIP 算法训练 一元三次方程
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 乘法表
    Java实现 蓝桥杯VIP 算法训练 乘法表
    监管只是压倒网盘业务的一根稻草,但不是主要原因(答案只有一个:成本!)
  • 原文地址:https://www.cnblogs.com/lichenwei/p/4873249.html
Copyright © 2011-2022 走看看