- compile 'org.greenrobot:eventbus:3.0.0'
(2) 在相关 Activity 中的 onCreat()、onDestory() 注册和解注 EventBus
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- EventBus.getDefault().register(this);
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- EventBus.getDefault().unregister(this);
- }
(3) 事件发布者如何发布事件
- EventBus.getDefault().post(实参);
我们到. 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;
- }
这里的. getDefault() 方法其实就是一个单例,获取到 EventBus 实例后调用 post 方法开始发布事件
post():
- /** Posts the given event to the event bus. */
- public void post(Object event) {
- PostingThreadState postingState = currentPostingThreadState.get();
- List eventQueue = postingState.eventQueue;
- eventQueue.add(event);
- if (!postingState.isPosting) {
- postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
- postingState.isPosting = true;
- if (postingState.canceled) {
- throw new EventBusException("Internal error. Abort state was not reset");
- }
- try {
- while (!eventQueue.isEmpty()) {
- postSingleEvent(eventQueue.remove(0), postingState);
- }
- } finally {
- postingState.isPosting = false;
- postingState.isMainThread = false;
- }
- }
- }
通过源码可以看得出来,方法的实参是一个对象类型的参数,参数会统一存储在 eventQueue 这个队列中,然后循环队列,将队列中的消息逐一发布,这里大家可能会想,每次 post 都会去调用整个队列么,那么不会造成方法多次调用么?
答案是不会的,因为在最外层加了一个判断,判断 event 是否被发不过,如果被发布过,则不会进入到这个方法内。
(4) 事件订阅者订阅事件
- @Subscribe
- public void onEventMainThread(实参){
- //接收到发布者发布的事件后,进行相应的处理操作
- }
这里要注意的是:EventBus 在 3.0 版本后,事件订阅监听的方法名可以随意起,不同于旧版本,名字是特定的。
- public void onEventMainThread(param)
- {
- //如果使用onEventMainThread作为订阅函数,那么不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,
- //这个在中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。
- }
- public void onEventPostThread(param)
- {
- //如果使用onEvent作为订阅函数,那么该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。
- //使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。
- }
- public void onEventBackgroundThread(param)
- {
- //如果使用onEventBackgrond作为订阅函数,那么如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。
- }
- public void onEventAsync(param)
- {
- //使用这个函数作为订阅函数,那么无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync.
- }
但是新版本需要手动的添加注解 @Subscribe(这是必不可少的)。既然名字可以随意起,那么又怎么控制在什么线程内进行处理呢?
- @Subscribe(threadMode = ThreadMode.MAIN)
给注解设置 ThreadMode 就可以了。
(5) 事件发布者和订阅者如何对应上
可以看到发布事件和订阅事件,都需要传入一个实参,而且在 post 方法中我们也看到了,这个实参是对象类型的,大家猜想的话也可以知道,发布和订阅事件是通过一个对象实参来进行关联的。
- public class TestEvent {
- private int mMsg;
- public TestEvent(int msg) {
- mMsg = msg;
- }
- public int getMsg(){
- return mMsg;
- }
- }
这个类很简单,只有一个变量和一个构造方法、get 方法。具体内容根据项目需求来定。
基本上了解这些就可以搞明白 EventBus 的使用了,下面上一下我写的 Demo,功能很简单,就是模仿下载的进度条,因为现在用的最多的是通过 handler 来进行处理的,而 EventBus 的出现,可以完美的代替 handler,
而且实现了解耦。
好,上代码!
MainActivity.class
- package com.example.wgh.eventbusdemo;
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.ProgressBar;
- import org.greenrobot.eventbus.EventBus;
- import org.greenrobot.eventbus.Subscribe;
- import org.greenrobot.eventbus.ThreadMode;
- public class MainActivity extends Activity {
- public ProgressBar progressBar = null;
- public int time = 0;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- while (time<100){
- time += 15;
- EventBus.getDefault().post(new TestEvent(time));
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }).start();
- }
- });
- progressBar = (ProgressBar) findViewById(R.id.progressbar);
- EventBus.getDefault().register(this);
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- EventBus.getDefault().unregister(this);
- }
- @Subscribe(threadMode = ThreadMode.MAIN)
- public void onEventMainThread(TestEvent event){
- progressBar.setProgress(event.getMsg());
- }
- }
activity_main.xml
- "1.0" encoding="utf-8"?>
- "http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/activity_main"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context="com.example.wgh.eventbusdemo.MainActivity"
- android:orientation="vertical">
- <ProgressBar
- android:id="@+id/progressbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="150dp"
- android:max="100"
- style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>
- <Button
- android:id="@+id/button"
- android:layout_marginTop="10dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="开始下载"/>
TestEvent.class
- public class TestEvent {
- private int mMsg;
- public TestEvent(int msg) {
- mMsg = msg;
- }
- public int getMsg(){
- return mMsg;
- }
- }
来源: