Eventbus3.0的基本使用

前言

EventBus是一个Android和Java的开源库,使用发布者/订阅者模式进行松散耦合。
当我们进行项目开发的时候,往往是需要应用程序的各组件、组件与后台线程间进行通信,比如在子线程中进行请求数据,当数据请求完毕后通过Handler或者是广播通知UI,而两个Fragment之家可以通过Listener进行通信等等。
我们平时开发的时候,当遇到Activity与Activity、Activity与Fragment之间的通信,往往采用Intent,又或者线程之间使用Handler进行通信,这样代码难免会复杂许多,而使用EventBus能极大简化两个组件之间的通信问题,而且效率极高,而EventBus升级到3.0版本后,开发者能够自定义订阅方法的名字,而没必要规定以“onEventXX”开头的方法了,这样也自由化了很多,而且支持了粘性事件的分发。

图解:

在这里插入图片描述

EventBus能为我们做什么?

  • 我们可以通过解耦发布者和订阅者简化Android事件传递。
  • EventBus可以代替Android传统的Intent,Handler,Broadcast或接口函数,在 Fragment,Activity,Service线程之间传递数据,执行方法。
  • 使代码简单,快,高性能:特别是在注重性能的Android上。也许在其同类的解决方案是最快的。
  • 小(jar包小于50K),但是强大:EventBus是一个很小的库,它的API超级简单。
  • android主线程传递:当和UI交互的时候,无论这个事件是怎么提交的,EventBus都可以在主线程传递事件。

关于EventBus

三要素

  • Event 事件。它可以是任意类型。
  • Subscriber
    事件订阅者。在EventBus3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。
  • Publisher
    事件的发布者。我们可以在任意线程里发布事件,一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。

四种线程模型

EventBus3.0有四种线程模型,分别是:

  • POSTING (默认) 表示事件处理函数的线程跟发布事件的线程在同一个线程。
  • MAIN 表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
  • BACKGROUND
    表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
  • ASYNC 表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。

如何使用

一、添加依赖

    implementation 'org.greenrobot:eventbus:3.1.1'

二、创建事件实体类:

所谓的事件实体类,就是传递的事件,一个组件向另一个组件发送的信息可以储存在一个类中,该类就是一个事件,会被EventBus发送给订阅者。
例如:

public class MessageEvent {
    public String name;
    public String password;

    public MessageEvent(String name, String password) {
        this.name = name;
        this.password = password;
    }
}

但在这里我们只使用String来演示

二、向EventBus注册,成为订阅者以及解除注册

通过以下代码:

EventBus.getDefault().register(this);

即可将当前类注册,成为订阅者,即对应观察者模式的“观察者”,一旦有事件发送过来,该观察者就会接收到匹配的事件。通常,在类的初始化时便进行注册,如果是Activity则在onCreate()方法内进行注册。

当订阅者不再需要接受事件的时候,我们需要解除注册,释放内存:

EventBus.getDefault().unregister(this);

三、声明订阅方法

在EventBus 3.0中,声明一个订阅方法需要用到@Subscribe注解,因此在订阅者类中添加一个有着@Subscribe注解的方法即可,方法名字可自定义,而且必须是public权限,其方法参数有且只能有一个,另外类型必须为第一步定义好的事件类型(比如上面的MessageEvent),如下所示:

 @Subscribe 
    public void onEvent(AnyEventType event) {
        /* Do something */
    }

四、具体使用

举一个例子,MainActivity打开CommonActivity,在CommonActivity发出一个事件,然后MainActivity做出相应的反馈。

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //首先要在你要接受EventBus的界面注册,这一步很重要
        EventBus.getDefault().register(this);

        Button btnCommon = (Button) findViewById(R.id.button);
        btnCommon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,CommonActivity.class);
                startActivity(intent);
            }
        });
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //在界面销毁的地方要解绑
        EventBus.getDefault().unregister(this);
    }

    //任意写一个方法,给这个方法一个@Subscribe注解,参数类型可以自定义,但是一定要与你发出的类型相同
    @Subscribe
    public void getEventBus(String str) {
        if (str != null) {
            //这里拿到事件之后吐司一下
            Toast.makeText(this,str, Toast.LENGTH_SHORT).show();

        }
    }
    //任意写一个方法,给这个方法一个@Subscribe注解,参数类型可以自定义,但是一定要与你发出的类型相同
    @Subscribe
    public void getEventBus2(String str) {
        if (str != null) {
            //得到事件刷新UI
            TextView textView =(TextView)findViewById(R.id.tv_1);
            textView.setText(str);
        }
    }
}

CommonActivity:

public class CommonActivity extends AppCompatActivity {

    Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_common);
        Button btnCommon = (Button) findViewById(R.id.button_1);
        btnCommon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                        EventBus.getDefault().post("hello!");
                        finish();
            }
        });
    }
}

效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

进一步认识@Subscribe注解

我们回头看看上面的订阅方法,添加了@Subscribe注解,该注解标识了当前方法为订阅方法,我们可以看到上面我们还可以给该注解赋值(threadMode = ThreadMode.MAIN)首先,我们看看@Subscribe的类文件:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
    ThreadMode threadMode() default ThreadMode.POSTING;

    /**
     * If true, delivers the most recent sticky event (posted with
     * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
     */
    boolean sticky() default false;

    /** Subscriber priority to influence the order of event delivery.
     * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
     * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
     * delivery among subscribers with different {@link ThreadMode}s! */
    int priority() default 0;
}

该注解内部有三个成员,分别是threadMode、sticky、priority。threadMode代表订阅方法所运行的线程,sticky代表是否是粘性事件,priority代表优先级。给这个三个成员赋不同的值,能使得订阅方法有着不同的效果。

1.ThreadMode是一个枚举类型,有着以下几个类型:

public enum ThreadMode {

    POSTING,

    MAIN,

    BACKGROUND,

    ASYNC
}

通过上文我们可以知道这几个类型的意思。

线程模式

我们把发送消息放到子线程,把接收消息放到主线程并且更新UI。

CommonActivity 里面发送消息放到子线程
 new Thread(new Runnable() {
                    @Override
                    public void run() {
                        EventBus.getDefault().post(666);
                        finish();
                    }
                }).start();

MainActivity里面接收事件,只需要指定线程模式即可,即threadMode = ThreadMode.MAIN

 @Subscribe(threadMode = ThreadMode.MAIN)
    public void getEventBus(Integer num) {
        if (num != null) {
            Toast.makeText(this, "num" + num, Toast.LENGTH_SHORT).show();
        }
    }

EventBus有4种线程模式,POSTING,MAIN,BACKGROUND,ASYNC,默认线程是POSTING。

2.priority 优先级

设置该优先级的目的是,当一个事件有多个订阅者的时候,优先级高的会优先接收到事件。

3.sticky 粘性事件

关于粘性事件,可以参考Android的广播机制,其中有一个粘性广播,粘性广播的意思是:该广播发送后,会保存在内存中,如果后来有注册的Receiver与之匹配,那么该Receiver便会接收到该广播。那么粘性事件同理,在注册之前便把事件发生出去,等到注册之后便会收到最近发送的粘性事件(必须匹配)。注意:只会接收到最近发送的一次粘性事件,之前的会接受不到。

最后

通过这次的学习更了解到到EventBus的使用,它对于们的的开发的确是十分的方便,能极大简化两个组件之间的通信问题,而且效率极高。EventBus的使用就说到这里,基本能满足我们的日常开发的需求了,文章中如果有任何错误欢迎指出,共同学习共同进步。

参考文章:
https://www.jianshu.com/p/1e8191bc7bc2
https://blog.csdn.net/bskfnvjtlyzmv867/article/details/71480647
https://blog.csdn.net/a553181867/article/details/52475213

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值