Android EventBus3.0实例使用详解及封装调用
来源:互联网 发布:凯文淘宝店 编辑:程序博客网 时间:2024/06/05 06:22
EventBus是一款Android下的发布/订阅事件总线机制。可以代替Intent、Handler、Broadcast等在Fragment、Activity之间传递消息。
优点:开销小,代码优雅。将发送者和接受者解耦。
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没什么不同。<br/>这里Subscribe中的key需要解释一下含义,Subscribe中可以传三种值:
ThreadMode:这是个枚举,有四个值,决定订阅函数在哪个线程执行
- PostThread:事件发送者在哪个线程就执行在哪个线程。同2.x中的onEvent方法,默认值就是这个
- MainThread:订阅函数一定执行在主线程。同onEventMainThread方法
- BackgroundThread:如果是事件从子线程发出,订阅函数就执行在那个子线程,不会创建新的子线程;如果主线程发出事件,则创建子线程。同onEventBackgroundThread方法
- Async:一定创建子线程。同onEventAsync方法。
sticky:默认为false,如果为true,当通过
postSticky
发送一个事件时,这个类型的事件的最后一次事件会被缓存起来,当有订阅者注册时,会把之前缓存起来的这个事件直接发送给它。使用在比如事件发送者先启动了,订阅者还没启动的情况。- priority:默认值为0。订阅了同一个事件的订阅函数,在ThreadMode值相同的前提下,收到事件的优先级。
Configuration用法:
当默认的EventBus不足以满足需求时,EventBusBuilder就上场了,EventBusBuilder允许配置各种需求的EventBus
例如1:当没有subscribers的时候,eventbus保持静默:EventBus eventBus = EventBus.builder().logNoSubscriberMessages(false) .sendNoSubscriberEvent(false).build();例如2:配置异常:默认情况下:eventbus捕获onevent抛出的异常,并且发送一个SubscriberExceptionEvent 可能不必处理EventBus eventBus = EventBus.builder().throwSubscriberException(true).build();
配置默认的eventbus单例
官方推荐:在application类中,配置eventbus单例,保证eventbus的统一
例如:配置eventbus 只在DEBUG模式下,抛出异常,便于自测,同时又不会导致release环境的app崩溃EventBus.builder().throwSubscriberException(BuildConfig.DEBUG).installDefaultEventBus();
Sticky Events用法:
前面说的一般的post event,正常流程,必须是先register,然后post event,handle event才能起作用。但是当我们post event时,还没有subcriber怎么办?但是又想后注册的subscriber,能收到消息,这时sticky event就开始大显身手了。
Warning:EventBus会把最后一个sticky event记录在内存中,然后分发给subscriber
来看下官方的Demo
1 post sticky event:EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));2 启动一个新的Activity,准备subscriber,注册后,所有的sticky subscriber的回调方法,会马上获得之前的sticky event@Overridepublic void onStart() { super.onStart(); EventBus.getDefault().register(this);}//注意这里sticky=true@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)public void onEvent(MessageEvent event) { // UI updates must run on MainThread textField.setText(event.message);}@Overridepublic void onStop() { EventBus.getDefault().unregister(this); super.onStop();}
Getting and Removing sticky Events manually
如上所述,当subscriber注册后,最后一个sticky event会自动匹配。但是,有些时候,主动去检查sticky event会更方便,并且 sticky event 需要remove,阻断继续传递。
官方demo
//返回的是之前的sticky eventMessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class);// Better check that an event was actually posted beforeif(stickyEvent != null) { // Now do something with it}
2中sticky event使用方法都可行,看业务需要和个人习惯,选择合适的使用方法
Priorities and Event Cancellation用法:
大多数情况下,eventbus不需要改变线程优先级,或者取消event,但是不排除少数情况,需要改变线程优先级。
Subscriber Priorities
官方demo
//priority默认为0,不同ThreadMode下的分发流程不受优先级的影响//优先级高的可以优先获得消息@Subscribe(priority = 1);public void onEvent(MessageEvent event) {…}
Cancelling event delivery
如果,不希望后续的subcriber收到消息,可以在收到消息后,调用cancelEventDelivery(Object event) 取消消息的后续传递。
官方demo
@Subscribepublic void onEvent(MessageEvent event){// Process the event…EventBus.getDefault().cancelEventDelivery(event) ;}
Note:一般情况下,event的取消发生在高优先级的subscriber
具体使用
创建事件:
public class FirstEvent { private String msg; public FirstEvent(String msg){ this.msg = msg; } public String getMsg(){ return msg; }}
使用场景一:在Activity之间通信传值
在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-1MainThread: mainPostThread: mainBackgroundThread: pool-1-thread-2
如果是在子线程中发送:
new Thread(new Runnable() { @Override public void run() { EventBus.getDefault().post(new FirstEvent("啦啦啦")); }}).start();
执行结果如下:
BackgroundThread: Thread-450PostThread: Thread-450Async: pool-1-thread-1MainThread: main
如果先启动SecondActivity,后启动MainActivity:
@Overridepublic 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)); } }); }}
使用场景二:完美替换Handler,在主线程更新UI,如下示例-模拟下载显示进度条
:
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()); }}
当然EventBus的功能并不局限这两种,还可以替换各种CallBack回调接口、StrartActivityForResult()等功能。
EventBus封装类:
/** * @author * @version 1.0 * @date 2016-3-31 上午10:59:22 * @describe EventBusUtils工具类 */public class EventBusUtils { public static void register(Object subscriber) { if (!EventBus.getDefault().isRegistered(subscriber)) { EventBus.getDefault().register(subscriber); } } public static void unregister(Object subscriber) { if(EventBus.getDefault().isRegistered(subscriber)){ EventBus.getDefault().unregister(subscriber); } } public static void sendEvent(EventBusEvent event) { EventBus.getDefault().post(event); } public static void sendStickyEvent(EventBusEvent event) { EventBus.getDefault().postSticky(event); } /** * 通过code码区分事件类型 */ public static final class EventCode { public static final int A = 0x111111; public static final int B = 0x222222; public static final int C = 0x333333; public static final int D = 0x444444; public static final int E = 0x555555; // other more }}/** * @author * @version 1.0 * @date 2017/5/12 17:01 * @describe EventBus事件类 * * 通过泛型<T>指定事件通信过程中的数据类型,code为事件码,使用的时候给不同的事件类型指定不同的code。 */public class EventBusEvent<T> { private int code; private T data; public EventBusEvent(int code) { this.code = code; } public EventBusEvent(int code, T data) { this.code = code; this.data = data; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public T getData() { return data; } public void setData(T data) { this.data = data; }}
最后,使用EventBus框架时候记得添加ProGuard 混淆规则
-keepattributes *Annotation*-keepclassmembers class ** { @org.greenrobot.eventbus.Subscribe <methods>;}-keep enum org.greenrobot.eventbus.ThreadMode { *; }# Only required if you use AsyncExecutor-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { <init>(java.lang.Throwable);}
- Android EventBus3.0实例使用详解及封装调用
- 【Android】- EventBus3.0使用详解
- Android EventBus3.0使用及源码解析
- EventBus3.0使用详解
- EventBus3.0使用详解
- EventBus3.0使用详解
- EventBus3.0使用详解
- EventBus3.0使用详解
- EventBus3.0使用详解
- EventBus3.0使用详解
- EventBus3.0使用详解
- EventBus3.0使用详解
- EventBus3.0的使用详解
- EventBus3.0配置及使用
- EventBus3.0原理及使用
- Android之EventBus1.0 和EventBus3.0的使用详解
- Android——EventBus3.0的使用详解
- EventBus3.0最新使用文档详解
- 工作中常用的gson解析
- parameter和argument的区别
- android USB gadget框架分析
- request、response 中文乱码问题与解决方式
- JavaScript 以及javaquery 函数自动加载运行
- Android EventBus3.0实例使用详解及封装调用
- main function has more than 200 local variables
- ios 什么时候调用layoutSubviews
- java流代码笔记
- drools简单示例
- 495. Teemo Attacking
- Tomcat Manager配置访问主机及添加用户
- Kafka入门经典教程
- 查看端口占用常用的命令(记录)