【Android实战】EventBus 更少的代码 更好的体验
2016-07-07 18:29
706 查看
简介
优点
项目实战
需求背景
步骤
相关介绍
线程模型
订阅优先级以及事件取消
粘性事件
总结
![](https://img-blog.csdn.net/20160707183142111)
EventBus的github地址
使你的代码更简单,代码可读性更好
快
小(~ 50K的jar包)
在安装量多达100,000,000+ 的应用中实践,表现优异
独具特色的功能,如线程分发,优先级订阅等。
![](https://img-blog.csdn.net/20160707180921690)
![](https://img-blog.csdn.net/20160707181044504)
多个页面涉及比赛预约的状态,一个页面预约或者取消预约成功,要即时更新其它页面的比赛预约状态
1、首先需要定义消息类,该类可以不继承任何基类也不需要实现任何接口
这里以LoginEvent(用户登录退出场景) 和AppointmentStateEvent (见注释)为例来介绍
2、在需要订阅事件的地方注册事件,在需要取消消息订阅的地方取消消息订阅
3、分发事件,即触发消息
![](https://img-blog.csdn.net/20160707160724357)
这里对BaseActivity小做解释:当通过插件化的方式加载暴风体育的时候,启动登录,通过startActivityForResult的方式调用主版的登录(之所以调用主版的登录是因为主应用和以插件化方式加载的暴风体育第三方登录(QQ,微信)的签名不同),当登录成功获取用户信息后,分发用户登录成功的消息
代码很简洁,具体相关操作如下:
4、消息处理
这里使用了最普通的方式,没有使用EventBus的注解模式,而且考虑到收到消息后的处理都是在主线程中完成,所以采用了onEventMainThread方法。
继承了BaseLoginActivity的Activity的相关处理:
![](https://img-blog.csdn.net/20160707160737444)
继承了BaseLoginFragment的Fragment的相关处理:
![](https://img-blog.csdn.net/20160707160752467)
注意:
在3.0之前,EventBus还没有使用注解方式。消息处理的方法也只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,分别代表四种线程模型。而在3.0之后,消息处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为PostThread)
事件处理函数的访问权限必须为public,否则会报异常
相关代码如下:
![](https://img-blog.csdn.net/20160707182411945)
![](https://img-blog.csdn.net/20160707165447744)
POSTING:
发布事件和接收事件在同一个线程
避免执行耗时操作,否则会阻塞事件的传递,有可能会引起ANR
MAIN:
无论事件从哪里发布,接收事件都在UI线程
可以用来更新UI,但是不能处理耗时操作
BACKGROUND:
发布事件来自主线程,接收事件则在新的线程中运行;发布事件来自子线 程,接收事件也在该子线程完成
禁止进行UI更新操作
ASYNC:
无论事件从哪里发布,接收事件都在新的子线程
禁止进行UI更新操作
优先级设置:
默认优先级是0,同样的线程分发模式,优先级更高的订阅者会先收到消息
不同线程模式的订阅者接收消息的顺序呢不受优先级影响
事件取消:
事件取消一般都是被高优先级的订阅者调用
严格限制在线程模式为POSTING的消息处理方法中
这里不做过多介绍,详情请参考Sticky Events
实战验证
高性能
基于API的简洁注解
主线程和子线程均可进行消息发布和订阅
事件以及订阅者继承特点
零配置且可配
码字!排版!画图!终于写完了!
优点
项目实战
需求背景
步骤
相关介绍
线程模型
订阅优先级以及事件取消
粘性事件
总结
简介
事件总线库,极大地简化了 Activities, Fragments, Threads, Services等各组件之间的通信。更少的代码,更好的体检EventBus的github地址
优点
简化组件之间的通信,对事件的发送者和接收者进行解耦;在Activity、Fragment、以及后台线程中运转良好;避免复杂和容易出错的依赖关系以及生命周期问题使你的代码更简单,代码可读性更好
快
小(~ 50K的jar包)
在安装量多达100,000,000+ 的应用中实践,表现优异
独具特色的功能,如线程分发,优先级订阅等。
项目实战
需求背景
登录、登出成功之后,涉及的相关页面要即时刷新登录数据,做出相应的调整多个页面涉及比赛预约的状态,一个页面预约或者取消预约成功,要即时更新其它页面的比赛预约状态
步骤
部分概念相关的可以参考下面的相关介绍穿插理解1、首先需要定义消息类,该类可以不继承任何基类也不需要实现任何接口
这里以LoginEvent(用户登录退出场景) 和AppointmentStateEvent (见注释)为例来介绍
public class OnEventBusInterface { public interface OnLoginListener { void onEventMainThread(LoginEvent event); } public interface OnTopicRefreshListener { void onEventMainThread(FollowTopicRefreshEvent event); } public interface OnAppointmentStateListener { void onEventMainThread(AppointmentStateEvent event); } public static class LoginEvent { private boolean hasLoginSucc; public LoginEvent(boolean loginSucc) { this.hasLoginSucc = loginSucc; } public boolean hasLoginSucc() { return hasLoginSucc; } public void setHasLoginSucc(boolean hasLoginSucc) { this.hasLoginSucc = hasLoginSucc; } } //FollowFragment刷新事件 public static class FollowTopicRefreshEvent { } /** * 在比赛详情页 * 比赛未开始 * 从首页直播tab进入或者从球队详情页的比赛tab进入 * 在比赛未开始时,可以预约或者取消预约比赛,这个操作完成后再返回上面两个入口时,需要刷新预约状态 * 这里传入了matchId作为参数,目前没有用到,因为现在比赛的预约与否是存在本地数据库的 * 如果以后预约比赛的状态和用户绑定在服务器,那么可能就需要使用这个matchId了 * <p/> * 需要3个有关注状态的地方 互相通知最新的关注状态 * add By SuS */ public static class AppointmentStateEvent { private String matchId; public AppointmentStateEvent(String matchId) { this.matchId = matchId; } public String getMatchId() { return matchId; } public void setMatchId(String matchId) { this.matchId = matchId; } }
2、在需要订阅事件的地方注册事件,在需要取消消息订阅的地方取消消息订阅
public class BaseLoginActivity extends BaseActivity implements OnEventBusInterface.OnLoginListener{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EventBus.getDefault().register(this);//注册EventBus } @Override public void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this);//反注册EventBus } protected void onLoginSuccess(){ } protected void onLoginOut(){ } public void onEventMainThread(OnEventBusInterface.LoginEvent event){ if(event.hasLoginSucc()){ onLoginSuccess(); }else{ onLoginOut(); } } }
public class BaseLoginFragment extends BaseFragment implements IHandlerMessage,OnEventBusInterface.OnLoginListener,OnEventBusInterface.OnTopicRefreshListener,OnEventBusInterface.OnAppointmentStateListener { protected Handler handler; @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); handler = new CommonHandler<BaseLoginFragment>(this); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); EventBus.getDefault().register(this);//注册EventBus } @Override public void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this);//反注册EventBus } @Override public void handlerCallback(Message msg) { } protected void showLoginWindow(){ StormUtils2.startLoginActivity(getActivity()); } protected void onLoginSuccess(){ } protected void onLoginOut(){ } protected void onFollowStatusChanged() {} protected void onAppointmentStateChanged(String matchId){ } public void onEventMainThread(OnEventBusInterface.LoginEvent event){ if(event.hasLoginSucc()){ onLoginSuccess(); }else{ onLoginOut(); } } public void onEventMainThread(OnEventBusInterface.FollowTopicRefreshEvent event){ onFollowStatusChanged(); } @Override public void onEventMainThread(OnEventBusInterface.AppointmentStateEvent event) { onAppointmentStateChanged(event.getMatchId()); } }
3、分发事件,即触发消息
这里对BaseActivity小做解释:当通过插件化的方式加载暴风体育的时候,启动登录,通过startActivityForResult的方式调用主版的登录(之所以调用主版的登录是因为主应用和以插件化方式加载的暴风体育第三方登录(QQ,微信)的签名不同),当登录成功获取用户信息后,分发用户登录成功的消息
代码很简洁,具体相关操作如下:
EventBus.getDefault().post(new OnEventBusInterface.LoginEvent(true));//登录成功
EventBus.getDefault().post(new OnEventBusInterface.LoginEvent(false));//登出成功
EventBus.getDefault().post(new OnEventBusInterface.AppointmentStateEvent(String.valueOf(matchInfo.getId())));//比赛预约状态改变成功
4、消息处理
这里使用了最普通的方式,没有使用EventBus的注解模式,而且考虑到收到消息后的处理都是在主线程中完成,所以采用了onEventMainThread方法。
继承了BaseLoginActivity的Activity的相关处理:
继承了BaseLoginFragment的Fragment的相关处理:
注意:
在3.0之前,EventBus还没有使用注解方式。消息处理的方法也只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,分别代表四种线程模型。而在3.0之后,消息处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为PostThread)
事件处理函数的访问权限必须为public,否则会报异常
相关代码如下:
public void onEventMainThread(OnEventBusInterface.LoginEvent event){ if(event.hasLoginSucc()){ onLoginSuccess(); }else{ onLoginOut(); } } public void onEventMainThread(OnEventBusInterface.FollowTopicRefreshEvent event){ onFollowStatusChanged(); } @Override public void onEventMainThread(OnEventBusInterface.AppointmentStateEvent event) { onAppointmentStateChanged(event.getMatchId()); }
相关介绍
线程模型
主要包括如下四种:POSTING:
发布事件和接收事件在同一个线程
避免执行耗时操作,否则会阻塞事件的传递,有可能会引起ANR
@Subscribe(threadMode = ThreadMode.POSTING) // ThreadMode is optional here public void onMessage(MessageEvent event) { log(event.message); }
MAIN:
无论事件从哪里发布,接收事件都在UI线程
可以用来更新UI,但是不能处理耗时操作
// Called in Android UI's main thread @Subscribe(threadMode = ThreadMode.MAIN) public void onMessage(MessageEvent event) { textField.setText(event.message); }
BACKGROUND:
发布事件来自主线程,接收事件则在新的线程中运行;发布事件来自子线 程,接收事件也在该子线程完成
禁止进行UI更新操作
// Called in the background thread @Subscribe(threadMode = ThreadMode.BACKGROUND) public void onMessage(MessageEvent event){ saveToDisk(event.message); }
ASYNC:
无论事件从哪里发布,接收事件都在新的子线程
禁止进行UI更新操作
// Called in a separate thread @Subscribe(threadMode = ThreadMode.ASYNC) public void onMessage(MessageEvent event){ backend.send(event.message); }
订阅优先级以及事件取消
尽管大多数情况下eventbus是不需要设置订阅的优先级和事件取消,但是某些特殊的场景可能派上用场。例如,当应用程序在前台,存在一个事件可能会触发一些用户界面相关逻辑,但当应用不可见时应该有不同的反应优先级设置:
默认优先级是0,同样的线程分发模式,优先级更高的订阅者会先收到消息
不同线程模式的订阅者接收消息的顺序呢不受优先级影响
@Subscribe(priority = 1); public void onEvent(MessageEvent event) { … }
事件取消:
事件取消一般都是被高优先级的订阅者调用
严格限制在线程模式为POSTING的消息处理方法中
// Called in the same thread (default) @Subscribe public void onEvent(MessageEvent event){ // Process the event … EventBus.getDefault().cancelEventDelivery(event) ; }
粘性事件
EventBus还支持发送黏性事件,就是在发送事件之后再订阅该事件也能收到该事件,能够收到订阅之前发送的消息。但是它只能收到最新的一次消息。这里不做过多介绍,详情请参考Sticky Events
总结
简单强大实战验证
高性能
基于API的简洁注解
主线程和子线程均可进行消息发布和订阅
事件以及订阅者继承特点
零配置且可配
码字!排版!画图!终于写完了!
相关文章推荐
- 5分钟搞定android混淆
- x264 android移植
- Android 通过JNI实现守护进程,使Service服务不被杀死
- 【Android】SQLite 数据库基本操作
- Android实战技巧之十二:Android Studio导入第三方类库、jar包和so库
- android 轮播图
- android判断应用是否有某个权限
- java.lang.Class Cast Exception: android.widget.HeaderViewListAdapter
- Android 中线程池的理解
- Android AsyncTask 的工作原理
- 高通平台串口调试 AP与模块串口通讯调试总结
- Android 4.4 kitkat以上及以下根据uri获取路径的方法
- Android开发常用到的中间View(加载,重试等)
- android平台短视频技术之 视频编辑的经验分享
- Android Studio导入第三方库(SlidingMenu)教程
- Android实现应用的增量更新\升级---其一
- Android VideoView状态跟踪和错误处理
- Android属性动画详解
- 关于Android栈的一些操作
- 有关Android中layout_weight的深处挖掘