EventBus3.0使用

作者: 聪明叉 | 来源:发表于2016-04-23 19:06 被阅读1152次

    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使用

        本文链接:https://www.haomeiwen.com/subject/uytfrttx.html