EventBus3.0开发详解 近万开发者收藏

什么是EventBus? eventBus是GreenRobot公司出品的一个基于【publish/subscribe】模型的开发库
1、GreenRobot公司除了出品eventBus还出品了比较有名的greenDao(sqlite数据库的orm开发框架)
EventBus3.0开发详解 近万开发者收藏
文章图片

可以看出GreenDao的star数为4581 而EventBus的star数更高 9564 (star数是一个框架/项目影响力的指标)
2、publish/subscribe是一个以发送消息与接收消息模型。以前咱们学习过相似的知识点有

  • sendBroadcast与BroadcastReceiver是一个典型
  • handler.sendMessage与handleMessage(Message msg)也是一个典型
  • 所以该模型主要包含两个方面 一个是发送消息 一个是接收消息
    EventBus3.0开发详解 近万开发者收藏
    文章图片
优点
  • 代码简洁、层次清晰,大大提高了代码的可读性和可维护性。
  • 可以通过简单的代码把数据传递给Activities, Fragments, Threads, Services等等
下载EventBus官方SDK Github下载地址为:https://github.com/greenrobot/EventBus
EventBus3.0的使用 可以更简单的在 app/build.gradle中,如下配置即可
EventBus3.0开发详解 近万开发者收藏
文章图片

然后运行gradle脚本
EventBus3.0开发详解 近万开发者收藏
文章图片

EventBus的方法非常简洁只要掌握以下方法基本就可以完成企业开发了
1、注册与移除
方法 功能描述
EventBus.getDefault().register(this) 注册
EventBus.getDefault().unregister(this) 解除
【EventBus3.0开发详解 近万开发者收藏】
以上两个方法使用上跟广播接收者的注册与使用是类似的有注册必须在使用后移除,以Activity为例:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EventBus.getDefault().register(this); }@Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); }

2、发送消息 发布消息的对象即为【publisher】发布者
EventBus.getDefault().post(new MainMessage(“Hello EventBus”));
Post参数类型为普通javaBean
public class MainMessage { private String msg; public MainMessage(String msg) { this.msg = msg; } public String getMsg() { return msg; } }

3、消息的接收处理(建议使用onEventXXX写法) 接收消息的对象即为【subscriber】 订阅者
//主线程中执行 @Subscribe(threadMode = ThreadMode.MainThread) public void onMainEventBus(MainMessage msg) { Log.d(TAG, "onEventBus() returned: " + Thread.currentThread()); }

@Subscribe在案例中会细细地讲解 因为是一个大重点
4、案例分析:代替请求码与响应码 MainActivity请求一个NextPageActivity要求该NextPageActivity关闭时把数据传回给MainActivity
startActivityForResult请求代码略
在zaowu.itheima.com.eventbusdemo.demo1.FistEvent创建消息类(给post作为发送内容)
public class FistEvent { private String msg; public FistEvent(String msg) { this.msg = msg; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }

zaowu.itheima.com.eventbusdemo.demo1.MainActivity
加载布局:layout/activity_main.xml
EventBus3.0开发详解 近万开发者收藏
文章图片

注册与移除 订阅者
public class MainActivity extends AppCompatActivity { privateTextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView= (TextView) findViewById(R.id.main_activity_tv); //注册事件 EventBus.getDefault().register(this); } @Override protected void onDestroy() { super.onDestroy(); //移除注册 EventBus.getDefault().unregister(this); } public void open(View view) { startActivity(new Intent(this, NextPageActivity.class)); }

编写订阅者接收消息方法
@Subscribe(threadMode = ThreadMode.MAIN) public void onEventMainThread(FistEvent event) { Log.i("itheima", "onEventMainThread:"+event.getMsg()+Thread.currentThread()); textView.setText(event.getMsg()); }

  • @Subscribe设置订阅者接收处理消息的方法
  • 可以给该注解配置线程参数@Subscribe(threadMode = ThreadMode.MAIN)
  • ThreadMode用来指定线程
zaowu.itheima.com.eventbusdemo.demo1.NextPageActivity点击发送消息并关闭
public class NextPageActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_next_page); } public void event1(View view) { //发送消息 FistEvent fistMessage = new FistEvent("NextPageActivity-FistEvent"); EventBus.getDefault().post(fistMessage); } }

运行前后
EventBus3.0开发详解 近万开发者收藏
文章图片
–>EventBus3.0开发详解 近万开发者收藏
文章图片

控件制台显示:消息已经由NextPageActivity传给MainActivity了。显示main主线程
EventBus3.0开发详解 近万开发者收藏
文章图片

不过首先注意一点eventBus将消息传给参数类型一致的方法
eventBus底层post出消息后,会查找作为subscriber订阅者的参数类型一致的方法然后向这些方法传递post出来的消息。
所以当订阅者有两个以上参数类型一致的方法时都会接收到消息。
EventBus3.0开发详解 近万开发者收藏
文章图片

建议开发者创建不同的javaBean类来代表不同的消息类型
ThreadMode原理 EventBus3.0开发详解 近万开发者收藏
文章图片

方法 功能描述
ThreadMode.MAIN 标注方法运行在主线程,可以更新UI
ThreadMode.BACKGROUND 标注方法运行在子线程,不可以更新UI但可以执行耗时代码
ThreadMode.POSTING 标注方法 运行在跟post一样的线程。如果post在主线程此时相当于MAIN,反之相当于BACKGROUND
ThreadMode.ASYNC 标注方法运行在子程。但是跟BACKGROUND有区别。举个例子如果ASYNC标注的方法将要运行时有一个BACKGROUND标注的方法正在运行(延时10秒),前者标注的方法不会等待10秒结束再运行,而是另外开一个线程运行

以下是EventBus的源代码分析
EventBus3.0开发详解 近万开发者收藏
文章图片

案例分析:代替广播接收者 如果掌握了EventBus就可以不用广播接收者来发送消息接收消息了,用EventBus更简洁。
1、创建不同的消息对象 zaowu.itheima.com.eventbusdemo.demo2.MainEvent
zaowu.itheima.com.eventbusdemo.demo2.BackGroundEvent
zaowu.itheima.com.eventbusdemo.demo2.AsyncEvent
zaowu.itheima.com.eventbusdemo.demo2.PostingEvent
public class MainEvent { private String msg; public MainEvent(String msg) { this.msg = msg; }public String getMsg() { return msg; }public void setMsg(String msg) { this.msg = msg; } }

2、发送不同的消息 layout/activity_threadmode.xml
zaowu.itheima.com.eventbusdemo.demo2.ThreadModeActivity
EventBus3.0开发详解 近万开发者收藏
文章图片

public void event1(View view) { //发送消息 MainEvent mainEvent = new MainEvent("MainEvent"); EventBus.getDefault().post(mainEvent); Log.i("itheima", "post(mainEvent); "+System.currentTimeMillis()); } public void event2(View view) { //发送消息 BackGroundEvent backGroundEvent = new BackGroundEvent("BackGroundEvent"); EventBus.getDefault().post(backGroundEvent); Log.i("itheima", "post(backGroundEvent); "+System.currentTimeMillis()); } public void event3(View view) { //发送消息 AsyncEvent asyncEvent = new AsyncEvent("AsyncEvent"); EventBus.getDefault().post(asyncEvent); Log.i("itheima", "post(asyncEvent); "+System.currentTimeMillis()); } public void event4(View view) { //发送消息 PostingEvent postingEvent = new PostingEvent("PostingEvent"); EventBus.getDefault().post(postingEvent); Log.i("itheima", "post(postingEvent); "+System.currentTimeMillis()); }

3、接收消息 zaowu.itheima.com.eventbusdemo.demo2.ThreadModeActivity
@Subscribe(threadMode = ThreadMode.MAIN) public void onMainEvent(MainEvent event) { Log.i("itheima", "onMainEvent接收事件:"+event.getMsg()+Thread.currentThread()+":"+System.currentTimeMillis()); } @Subscribe(threadMode = ThreadMode.BACKGROUND) public void onBackGroundEvent(BackGroundEvent event) { try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } Log.i("itheima", "onBackGroundEvent接收事件:"+event.getMsg()+Thread.currentThread()+":"+System.currentTimeMillis()); } @Subscribe(threadMode = ThreadMode.ASYNC) public void onAsyncEvent(AsyncEvent event) { Log.i("itheima", "AsyncEvent接收事件:"+event.getMsg()+Thread.currentThread()+":"+System.currentTimeMillis()); } @Subscribe(threadMode = ThreadMode.POSTING) public void onPostingEvent(PostingEvent event) { Log.i("itheima", "onPostingEvent接收事件:"+event.getMsg()+Thread.currentThread()+":"+System.currentTimeMillis()); }

运行结果【按点击顺序】
EventBus3.0开发详解 近万开发者收藏
文章图片

【1】的运行结果为 ThreadMode.MAIN
EventBus3.0开发详解 近万开发者收藏
文章图片

【2】的运行结果为ThreadMode.BACKGROUND
消息发送到接收到经过了10秒 且运行在子线程
EventBus3.0开发详解 近万开发者收藏
文章图片

【3】的运行结果为ThreadMode.POSTING 与post在一个线程
EventBus3.0开发详解 近万开发者收藏
文章图片

【4】测试ThreadMode.ASYNC时按以下顺序
EventBus3.0开发详解 近万开发者收藏
文章图片

运行结果为
EventBus3.0开发详解 近万开发者收藏
文章图片

说明与ThreadMode.BACKGROUND都是子线程。但是如果后台有BACKGROUND在运行,ASYCN消息不会等待BACKGOUND完成,而是直接运行。
总结 有了EeventBus代码会更简洁。同时它比handler,广播,内容观察者的实现都简洁统一还支持消息接收的线程指定。开发者重点握:ThreadMode变量
原文出处:http://bbs.itheima.com/thread-299831-1-1.html
HermesEventBus https://github.com/eleme/HermesEventBus
HermesEventBus是一个基于EventBus的、能在进程间发送和接收event的库,在IPC或者插件开发中非常有用。它底层基于EventBus,并且和EventBus有相同API。
EventBus是Android系统上使用最广泛的简化模块之间通信的库。但它不支持进程间收发事件。
所以,我开发了HermesEventBus来支持进程间事件收发。
注意:本库基于EventBus 3.0.0。如果你之前使用的是老版本,那么必须修改你的代码,否则将无法接收event。但是修改比较简单。
之前使用“onEventXXX”名字的方法要加上注解,并且在后面附上线程模式:
@Subscribe(threadMode = ThreadMode.MAIN) public void showText(String text) { textView.setText(text); }

原理 本库基于两个库开发:Hermes和EventBus。
事件收发是基于EventBus,IPC通信是基于Hermes。Hermes是一个简单易用的Android IPC库。

本库首先选一个进程作为主进程,将其他进程作为子进程。
每次一个event被发送都会经过以下四步:
1、使用Hermes库将event传递给主进程。
2、主进程使用EventBus在主进程内部发送event。
3、主进程使用Hermes库将event传递给所有的子进程。
4、每个子进程使用EventBus在子进程内部发送event。
另外还使用了Concurrent-Utils库。
用法 本库能在app内实现多进程event收发,也可以跨app实现event收发。
单一app内的用法 如果你在单一app内进行多进程开发,那么只需要做以下三步:
Step 1
在gradle文件中加入下面的依赖:
dependencies { compile 'xiaofei.library:hermes-eventbus:0.3.0' }

如果你使用Maven,那么加入下面的依赖:
xiaofei.library hermes-eventbus 0.3.0 pom

Step 2
在Application的onCreate中加上以下语句进行初始化:
HermesEventBus.getDefault().init(this);

Step 3
每次使用EventBus的时候,用HermesEventBus代替EventBus。
HermesEventBus.getDefault().register(this); HermesEventBus.getDefault().post(new Event());

HermesEventBus也能够在一个进程间传递event,所以如果你已经使用了HermesEventBus,那么就不要再使用EventBus了。
Step 4
如果进程不需要再发送和接受event,那么这个进程必须调用:
HermesEventBus.getDefault().destroy();

否则你会收到android.os.DeadObjectException和其他一些异常。这些异常会打印一些异常信息但不会导致app崩溃。
多个app间的用法(使用DroidPlugin的时候就是这种情况) 如果你想在多个app间收发event,那么就做如下几步:
Step 1
在每个app的gradle文件中加入依赖:
dependencies { compile 'xiaofei.library:hermes-eventbus:0.3.0' }

如果使用Maven,那么就加入下面的依赖:
xiaofei.library hermes-eventbus 0.3.0 pom

Step 2
选择一个app作为主app。你可以选择任意app作为主app,但最好选择那个存活时间最长的app。
在使用DroidPlugin的时候,你可以把宿主app作为主app。
在主app的AndroidManifest.xml中加入下面的service:
"xiaofei.library.hermes.HermesService$HermesService0"/>

你可以加上一些属性。
Step 3
在app间收发的事件类必须有相同的包名、相同的类名和相同的方法。
务必记住在代码混淆的时候将这些类keep!!!
Step 4
在主app的application类的onCreate方法中加入:
HermesEventBus.getDefault().init(this);

在其他app的Application类的onCreate方法中加入:
HermesEventBus.getDefault().connectApp(this, packageName);

“packageName”指的是主app的包名。
Step 5
每次使用EventBus的时候,用HermesEventBus代替EventBus。
HermesEventBus.getDefault().register(this); HermesEventBus.getDefault().post(new Event());

HermesEventBus也能够在一个进程间传递event,所以如果你已经使用了HermesEventBus,那么就不要再使用EventBus了。
Step 6
如果进程不需要再发送和接受event,那么这个进程必须调用:
HermesEventBus.getDefault().destroy();

否则你会收到android.os.DeadObjectException和其他一些异常。这些异常会打印一些异常信息但不会导致app崩溃。
友情链接 Xiaofei’s GitHub: https://github.com/Xiaofei-it
Hermes是一套新颖巧妙易用的Android进程间通信IPC框架。
Shelly是一个面向业务逻辑的编程库。Shelly库提供了一种全新的编程模式,将业务对象的变化对各个模块的影响通过方法链表示出来。
AndroidDataStorage是一个简洁易用并且具有高性能的Android存储库。
ComparatorGenerator是一个易用的生成Comparator的工具类。在排序时特别有用。

    推荐阅读