EventBus3.0使用

EventBus是使用十分广泛的事件总线框架, 2.0到3.0的变化还是挺大的

今天准备重构代码,关于解耦想到了用EventBus,发现EventBus出了3.0的beta版,使用方式略有区别,特此记录。如果不会用EventBus的,请参考教程。

3.0与2.x的区别

主要区别在订阅函数的不同

EventBus2.x中只暴露了四个方法供用户调用,分别是

  • onEvent:该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。
  • onEventMainThread:不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。
  • onEventBackgroundThread:如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。
  • onEventAsync:无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync.

EventBus3.0中必须使用注解,例如:

@Subscribe(threadMode = ThreadMode.Async, sticky = true, priority = 1)
public void firstEvent(FirstEvent event) {
    Log.e("TAG", "Async" + Thread.currentThread().getName());
}

好处在于订阅函数可以随便起名字,其他与2.x没什么不同。
这里Subscribe中的key需要解释一下含义,Subscribe中可以传三种值:

  • ThreadMode:这是个枚举,有四个值,决定订阅函数在哪个线程执行

    • PostThread:事件发送者在哪个线程就执行在哪个线程。同2.x中的onEvent方法,默认值就是这个
    • MainThread:订阅函数一定执行在主线程。同onEventMainThread方法
    • BackgroundThread:如果是事件从子线程发出,订阅函数就执行在那个子线程,不会创建新的子线程;如果主线程发出事件,则创建子线程。同onEventBackgroundThread方法
    • Async:一定创建子线程。同onEventAsync方法。
  • sticky:默认为false,如果为true,当通过postSticky发送一个事件时,这个类型的事件的最后一次事件会被缓存起来,当有订阅者注册时,会把之前缓存起来的这个事件直接发送给它。使用在比如事件发送者先启动了,订阅者还没启动的情况。

  • priority:默认值为0。订阅了同一个事件的订阅函数,在ThreadMode值相同的前提下,收到事件的优先级。

具体使用

创建事件:

public class FirstEvent {
    private String msg;
    public FirstEvent(String msg){
        this.msg = msg;
    }
    public String getMsg(){
        return msg;
    }
}

在MainActivity的onCreate方法中注册,onDestroy方法中反注册

EventBus.getDefault().register(this);
EventBus.getDefault().unregister(this);

订阅函数,此处用来查看执行在哪个线程(注意,这里的函数名可以任取):

@Subscribe(threadMode = ThreadMode.Async, sticky = true, priority = 1)
public void onAsync(FirstEvent event) {
    Log.e("TAG", "Async: " + Thread.currentThread().getName());
}

@Subscribe(threadMode = ThreadMode.BackgroundThread)
public void onBackgroundThread(FirstEvent event) {
    Log.e("TAG", "BackgroundThread: " + Thread.currentThread().getName());
}

@Subscribe(threadMode = ThreadMode.MainThread)
public void onMainThread(FirstEvent event) {
    Log.e("TAG", "MainThread: " + Thread.currentThread().getName());
}

@Subscribe(threadMode = ThreadMode.PostThread)
public void onPostThread(FirstEvent event) {
    Log.e("TAG", "PostThread: " + Thread.currentThread().getName());
}

在SecondActivity发送事件(主线程中发送):

EventBus.getDefault().post(new FirstEvent("啦啦啦"));

执行结果如下:

Async: pool-1-thread-1
MainThread: main
PostThread: main
BackgroundThread: pool-1-thread-2

如果是在子线程中发送:

new Thread(new Runnable() {
    
    @Override
    public void run() {
        EventBus.getDefault().post(new FirstEvent("啦啦啦"));
    }
}).start();

执行结果如下:

BackgroundThread: Thread-450
PostThread: Thread-450
Async: pool-1-thread-1
MainThread: main

如果先启动SecondActivity,后启动MainActivity:

@Override
public void onClick(View v) {
    EventBus.getDefault().postSticky(new FirstEvent("啦啦啦"));
    startActivity(new Intent(SecondActivity.this,MainActivity.class));
}

确实只有onAsync方法收到了消息。

至此对EventBus的试验基本就结束了,各位可以自行选择不同的ThreadMode值,让订阅函数执行在不同的线程。根据需要选择是否需要sticky=true。

完整的MainActivity和SecondActivity代码如下(xml文件就不贴了,就一个Button):

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EventBus.getDefault().register(this);
        findViewById(R.id.btn).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this,
                        SecondActivity.class));
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

    @Subscribe(threadMode = ThreadMode.Async, sticky = true, priority = 1)
    public void onAsync(FirstEvent event) {
        Log.e("TAG", "Async: " + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.BackgroundThread)
    public void onBackgroundThread(FirstEvent event) {
        Log.e("TAG", "BackgroundThread: " + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.MainThread)
    public void onMainThread(FirstEvent event) {
        Log.e("TAG", "MainThread: " + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.PostThread)
    public void onPostThread(FirstEvent event) {
        Log.e("TAG", "PostThread: " + Thread.currentThread().getName());
    }

}


public class SecondActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        findViewById(R.id.second).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                EventBus.getDefault().postSticky(new FirstEvent("Lai自星星的我"));
                startActivity(new Intent(SecondActivity.this,MainActivity.class));
            }
        });
    }

}

参考链接

EventBus所有版本的Marven仓库
EventBus2.x使用教程
快速Android开发系列通信篇之EventBus

你可能感兴趣的:(EventBus3.0使用)