Android EventBus的使用

简介: Android EventBus的使用

EventBus 是一个开源库,他利用 发布/订阅 者模式来对项目进行解耦,他可以利用很少的代码,来实现多组件的通信。android 的多组件通信可以通过 Handler,广播等,但使用他们进行通信 代码量非常多,组件之间容易产生耦合。


1,基本使用


添加依赖:


compile 'org.greenrobot:eventbus:3.1.1'


定义事件,可以是普通的对象例如:


public class EventMessage {
    private int type;
    private String message ;
  ......
    public EventMessage(int type, String message) {
        this.type = type;
        this.message = message;
    }
    @Override
    public String toString() {
        return "type="+type+"--message= "+message;
    }
}


注册订阅之 和 注销订阅者,只有订阅者注册了,他们才会收到时间。在Android 中,可以根据 Activity 或者 Fragment 的生命周期来注册和注销。如:


@Override
    protected void onStart() {
        super.onStart();
        // 注册订阅者
        EventBus.getDefault().register(this);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //注销订阅者
        EventBus.getDefault().unregister(this);
    }


然后就可以发布事件了,在需要的地方发布事件,所有订阅了该事件类型并进行注册的订阅者将会接收到该事件。如:


// 发布事件
 EventMessage msg = new EventMessage(1,"main2Activity");
 EventBus.getDefault().post(msg);


最后还需要一个接受事件的地方,也就是订阅事件,订阅者需要定义事件的处理方法(也称之为 订阅之方法),当发布对应事件类型时,该方法被调用。 EventBus3 采用 @Subscribe 注解来定义订阅者方法。方法可以是任意的合法方法名,参数类型为订阅事件的类型。如:


/**
     * 订阅事件
     * @param message 
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onReceiveMsg(EventMessage message){
        Log.e("-------", "onReceiveMsg: "+message );
    }


下面看一个例子


public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    protected void onStart() {
        super.onStart();
        // 注册订阅者
        EventBus.getDefault().register(this);
    }
    @Override
    protected void onResume() {
        super.onResume();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            startActivity(new Intent(MainActivity.this,Main2Activity.class));
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //注销订阅者
        EventBus.getDefault().unregister(this);
    }
    /**
     * 订阅者方法
     * @param message 参数
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onReceiveMsg(EventMessage message){
        Log.e("-------", "onReceiveMsg: "+message );
        Toast.makeText(getApplicationContext(), "哈哈", Toast.LENGTH_SHORT).show();
    }
}


public class Main2Activity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        findViewById(R.id.main2_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 发布事件
                EventMessage msg = new EventMessage(1,"main2Activity");
                EventBus.getDefault().post(msg);
            }
        });
    }
}


当 MainActivity 启动后的三秒 , 然后启动Main2Activity,点击按钮发送事件,然后 MainActivity 中的订阅事件的方法就会得到执行。


结果如下:


-------: onReceiveMsg: type=1--message= main2Activity


2,线程模式


EventBus 支持订阅者方法在不同的发布事件所在线程中被调用,你可以在订阅事件的时候在注解中指定

这个方法所执行的线程!


ThreadMode.POSTING


订阅者发布的事件将会在所在的线程调用,这是默认的模式。时间的传递是同步的,一旦发布事件,所有对该模式 的订阅事件都会执行。这种线程模式意味着最少的性能开销,因为它避免了线程的切换。因此,对于不要求是主线程并且耗时很短的简单任务推荐使用该模式。使用该模式的订阅者方法应该快速返回,以避免阻塞发布事件的线程,这可能是主线程。


ThreadMode.MAIN


订阅方法在主线程(UI)调用 ,因此可以直接更新 UI ,如果发布事件的线程是主线程,那么该模式的订阅者方法将被直接调用。使用该模式的订阅者方法必须快速返回,以避免阻塞主线程。


ThreadMode.MAIN_ORDERED


订阅方法在主线程(UI)调用,因此可以直接更新UI,事件将先进入队列然后才发送给订阅者,所以发布事件的调用将立即返回。这使得事件的处理保持严格的串行顺序。使用该模式的订阅者方法必须快速返回,以避免阻塞主线程。


ThreadMode.BACKGROUND


订阅者方法 将在 后台线程中被调用,如果发布事件的线程不是主线程,那么订阅者方法将会直接在该线程被调用。如果是主线程,那么将会使用一个单独的后台线程,该线程将按顺序发送所有的事件。使用该模式的订阅者方法应该快速返回,以避免阻塞后台线程。


ThreadMode.ASYNC


订阅者方法将在一个单独的线程中被调用。因此,发布事件的调用者将立即返回。。如果订阅者方法的执行需要一些时间,例如网络访问,那么就应该使用该模式。避免触发大量的长时间运行的订阅者方法,以限制并发线程的数量。EventBus使用了一个线程池来有效地重用已经完成调用订阅者方法的线程。


E/MainActivity: onMessageMain(), current thread is main
 E/MainActivity: onMessagePosting(), current thread is main
 E/MainActivity: onMessageBackground(), current thread is pool-1-thread-2
 E/MainActivity: onMessageAsync(), current thread is pool-1-thread-1
 E/MainActivity: onMessageMainOrdered(), current thread is main


在主线程发布事件,调用如上所示


3,粘性事件


如果先发布了事件,然后有订阅者订阅了事件,那么除非再次发布该事件,否则订阅者将永远接收不到该事件。此时可以使用粘性事件。发布一个粘性事件后,EventBus 将在内存中缓存该粘性事件。当有订阅者订阅了该粘性事件,订阅者将接收到该事件


下面看一个例子:


public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.tv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 发布事件
                EventMessage msg = new EventMessage(1,"mainActivity");
                EventBus.getDefault().postSticky(msg);
                Toast.makeText(MainActivity.this, "发布粘性事件", Toast.LENGTH_SHORT).show();
                startActivity(new Intent(MainActivity.this,Main2Activity.class));
            }
        });
    }
}


public class Main2Activity extends AppCompatActivity {
    private static final String TAG = "Main2Activity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        // 注册订阅者
        EventBus.getDefault().register(this);
    }
    @Subscribe(threadMode = ThreadMode.POSTING ,sticky =true)
    public void onMessage(EventMessage event) {
        Toast.makeText(this, "收到粘性事件", Toast.LENGTH_SHORT).show();
        Log.e(TAG, "onMessagePosting(), current thread is " + Thread.currentThread().getName());
        //移除粘性事件
        EventBus.getDefault().removeStickyEvent(event);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //注销订阅者
        EventBus.getDefault().unregister(this);
    }
}


在上面 MainActivity 中,发布了一个粘性事件,注意发送的时候订阅者没有订阅,也没有订阅者方法,发布后直接跳转到 Main2Activity 中,然后在进行注册,定义订阅者方法。最后这个订阅者方法就会得到执行。


总的来看,粘性事件就是在订阅者未注册的时候发布事件,然后在订阅之后还可以接收到的事件。


3,事件优先级


EventBus 支持在订阅者方法中指定事件传递的优先级,默认情况下,订阅者方法的时间传递优先级为 0,数值越大,优先级越高。在相同的线程模式下,更高的优先级订阅者方法将优先接收到事件。注意:优先级只有在相同的线程模式下才有效。


如下订阅者方法:


@Subscribe(threadMode = ThreadMode.POSTING ,sticky =true,priority = 2)
    public void onMessage(EventMessage event) {
        Log.e(TAG, "onMessagePosting(), current thread is " + Thread.currentThread().getName());
        EventBus.getDefault().removeStickyEvent(event);
}


在上面这个订阅者方法中,制定了优先级为 2。


你也可以在优先级高的订阅者方法接收到时间后取消事件的传递。此时,低优先级的订阅者方法将不会收到该事件。注意:订阅者方法只有在线程模式为 ThreadMode.POSTING 时,才可以取消一个事件的传递。如下


@Subscribe(threadMode = ThreadMode.POSTING ,sticky =true,priority = 2)
    public void onMessage(EventMessage event) {
        //取消事件传递
        EventBus.getDefault().cancelEventDelivery(event);
    }


4,订阅者索引


默认情况下,EventBus 查找订阅者方法时采用的是反射,订阅者索引可以加速订阅者的注册,是一个可选的优化。其原理是:使用 EventBus 的注解处理器在应用构建期间创建订阅者索引类,该类包含了订阅者和订阅者方法的相关信息。EventBus 官方推荐在 Android 中使用订阅者索引以获得最佳的性能。


要开启订阅者索引的生成,你需要在构建脚本中使用annotationProcessor属性将EventBus的注解处理器添加到应用的构建中,还要设置一个eventBusIndex参数来指定要生成的订阅者索引的完全限定类名。


//订阅者索引,在 android defaultConfig 中,加入如下:
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [eventBusIndex: 'com.testdemo.www.eventbus.MainActivityIndex']
            }
        }
        //最后加入
        annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'


然后 Rebuild 会生成一个类


public class MainActivityIndex implements SubscriberInfoIndex {
    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;
    static {
        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();
        putIndex(new SimpleSubscriberInfo(MainActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onMessage", EventMessage.class, ThreadMode.POSTING, 3, false),
            new SubscriberMethodInfo("onMessageOne", EventMessage.class, ThreadMode.POSTING, 4, false),
        }));
    }
    private static void putIndex(SubscriberInfo info) {
        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
    }
    @Override
    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
        if (info != null) {
            return info;
        } else {
            return null;
        }
    }
}


在自定义的 Application 中


public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        //配置EventBus
        EventBus.builder().addIndex(new MainActivityIndex()).installDefaultEventBus();
    }
}


然后正常使用即可


相关文章
|
Java Android开发 Kotlin
Android | 这是一份详细的 EventBus 使用教程 | 牛气冲天新年征文
Android | 这是一份详细的 EventBus 使用教程 | 牛气冲天新年征文
826 0
Android | 这是一份详细的 EventBus 使用教程 | 牛气冲天新年征文
|
Android开发
Android基础入门:EventBus实现总线数据分发
我们之前学习了Activity-》Activity中的数据传送,是通过intent.putExtra()方法实现的,如果要实现Activity-》Fragment或者Fragment-》Fragment都是不方便的,通过EventBus能很好的解决这个问题
204 0
|
调度 Android开发
【EventBus】发布-订阅模式 ( Android 中使用 发布-订阅模式 进行通信 )
【EventBus】发布-订阅模式 ( Android 中使用 发布-订阅模式 进行通信 )
354 0
【EventBus】发布-订阅模式 ( Android 中使用 发布-订阅模式 进行通信 )
|
XML Java Android开发
|
Android开发
Android EventBus使用(不含源码解析)
官方文档:https://github.com/greenrobot/EventBus simplifies the communication between components decouples event senders and receiv...
1439 0
|
Android开发 Java 数据格式
Android项目实战(十三):浅谈EventBus
原文:Android项目实战(十三):浅谈EventBus 概述: EventBus是一款针对Android优化的发布/订阅事件总线。 主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service。
1026 0
|
缓存 Java Android开发
Android——EventBus源码分析
停停走走又几天,断断续续这一年。时间还是如此之快,转眼间又到了17年的末尾了。趁着这些天还能静下心来看看代码,赶紧记录下自己的心得。 这一周,工作任务不多,总是想要看点什么但又不清楚该看啥,有些迷茫~不过既然自己还想要在Android路上继续前行,那么请深入探索吧! OK,闲话不多说。
735 0
|
Android开发
simple Android EventBus code
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.
715 0
|
Android开发
Android应用开发—eventBus发布事件和事件处理的时序关系
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/voidreturn/article/details/78334378 占坑,简单说明下eventBus发布事件和事件处理的时序关系。
1311 0