EventBus详解

简介

github原文

EventBus...

* simplifies the communication between components
- decouples event senders and receivers
- performs well with Activities, Fragments, and background threads
- avoids complex and error-prone dependencies and life cycle issues
- makes your code simpler
* is fast
* is tiny (<50k jar)
* is proven in practice by apps with 100,000,000+ installs
* has advanced features like delivery threads, subscriber priorities, etc.

大概意思

EventBus...
* 简化组件之间的通信
- 发送者和接收者解耦
- 可以在Activities, Fragments,background threads(服务、子线程等)之间传递数据
- 避免了依赖和生命周期等容易出错的问题
- 让你的程序看上去更简洁
* 更快
* 更小(jar包大小小于50k)
* 已经有这么这么多应用用过了EventBus。
* 有一些更高级的功能...

看过简介,应该大概知道EventBus是一个什么东西了吧

Github源码

源码地址:https://github.com/greenrobot/EventBus

API文档地址:https://github.com/greenrobot/EventBus/blob/master/HOWTO.md

个人对EventBus的理解

首先要导入jar包,这个就不用多说了,然后要有一个发送者发送一个消息,最后要有一个接收者接收发送过来的消息

因此,在你要给某个接收者发送消息的时候,一定要保证接收者已经注册了,否者接收者都还没有,谁来接收呢。

为什么提到这个呢,因为我刚用的时候,我是想在一个Activity1里开启另一个Activity2,然后用EventBus传递过去一个数据,于是我发送了一个消息,然后用Intent开启另外一个Activity2,在Activity2里注册了接收者,但是却没有收到消息,之后我又先开启Activity2,等初始化好了以后,再发送消息,Activity2就收到消息了

所以想一下EventBus的应用场景,如果我们有一个服务要在后台一直刷数据,然后在界面上显示,类似这种场景,我们就可以用EventBus来实现

普通的页面跳转需要传递的数据,我们用Intent就完全可以啦。

导入jar包

在Gradle文件里加上jar包

消息发送者

非常简单,就一行代码

EventBus.getDefault().post(new MessageEvent("Hello everyone!"));

这里需要传递一个数据对象,就是一个普通的Javabean

public class MessageEvent {
public final String message; public MessageEvent(String message) {
this.message = message;
}
}

消息接收者

注册接收者

EventBus.getDefault().register(this);

反注册接收者

EventBus.getDefault().unregister(this);

四个接收方法

  • PostThread: Subscriber will be called in the same thread, which is posting the event. This is the default. Event delivery implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for simple tasks that are known to complete is a very short time without requiring the main thread. Event handlers using this mode should return quickly to avoid blocking the posting thread, which may be the main thread. Example:
  • 大概意思: 发送者和接收者要在同一个线程,默认是使用这种方式接收,因为他避免了线程的切换,性能开销更小
// Called in the same thread (default)
public void onEvent(MessageEvent event) {
log(event.message);
}
  • MainThread: Subscriber will be called in Android’s main thread (sometimes referred to as UI thread). If the posting thread is the main thread, event handler methods will be called directly. Event handlers using this mode must return quickly to avoid blocking the main thread. Example:
  • 大概意思: 接收者在主线程(UI线程),因为是在主线程,所以要避免耗时操作阻塞线程。
// Called in Android UI's main thread
public void onEventMainThread(MessageEvent event) {
textField.setText(event.message);
}
  • BackgroundThread: Subscriber will be called in a background thread. If posting thread is not the main thread, event handler methods will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single background thread that will deliver all its events sequentially. Event handlers using this mode should try to return quickly to avoid blocking the background thread.
  • 大概意思: 接收者是和发送者在同一个后台线程中接收到消息(它和发送者是在一个线程中,后面有测试),所以如果发送者是在主线程,那么接收者也是在同一个主线程,所以尽量避免耗时的操作阻塞线程。
// Called in the background thread
public void onEventBackgroundThread(MessageEvent event){
saveToDisk(event.message);
}
  • Async: Event handler methods are called in a separate thread. This is always independent from the posting thread and the main thread. Posting events never wait for event handler methods using this mode. Event handler methods should use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number of long running asynchronous handler methods at the same time to limit the number of concurrent threads. EventBus uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications.
  • 大概意思: 异步的形式,发送者和接收者不是同一个线程, 如果有一些耗时的操作,例如联网获取一些数据等情况,可以用异步,但是为了避免同时有太多的并行事件,要尽量限制并发线程的数量
// Called in a separate thread
public void onEventAsync(MessageEvent event){
backend.send(event.message);
}

案例

后台一个Service刷数据,页面显示数据

Demo源码

下载地址(Android Studio工程):http://download.csdn.net/detail/q4878802/9057545

效果图

Activity

package com.kongqw.kqweventbusdemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView; import com.kongqw.kqweventbusdemo.bean.MessageEvent;
import com.kongqw.kqweventbusdemo.service.KqwService; import de.greenrobot.event.EventBus; public class MainActivity extends Activity { private TextView mTvShow; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 显示信息的TextView
mTvShow = (TextView) findViewById(R.id.tv_show);
// 开启服务 刷数据
Intent service = new Intent(this, KqwService.class);
startService(service);
} @Override
public void onStart() {
EventBus.getDefault().register(this);
super.onStart();
} @Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
} // Called in Android UI's main thread
public void onEventMainThread(MessageEvent event) {
mTvShow.setText("onEventMainThread : \n" + event.message);
}
}

Service

package com.kongqw.kqweventbusdemo.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log; import com.kongqw.kqweventbusdemo.bean.MessageEvent; import de.greenrobot.event.EventBus; public class KqwService extends Service {
public KqwService() {
} @Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
} @Override
public void onCreate() {
super.onCreate(); EventBus.getDefault().post(new MessageEvent("Service 传递过来的数据"));
/*
* 模拟网络刷新数据
*/
new Thread() {
@Override
public void run() { for (int x = 0; x < Integer.MAX_VALUE; x++) {
try {
sleep(1000);
EventBus.getDefault().post(new MessageEvent("Service 传递过来的数据 : " + x));
long id = Thread.currentThread().getId();
Log.d("KqwService", "Service发送了数据:" + x + "线程ID : " + id);
} catch (Exception e) {
// TODO
Log.d("KqwService", "error :" + e);
}
}
}
}.start();
}
}

XML页面

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"> <TextView
android:id="@+id/tv_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示数据"
android:textSize="25dp" /> </RelativeLayout>

测试onEvent

  • 测试发送者和接收者在同一个线程
// This method will be called when a MessageEvent is posted
public void onEvent(MessageEvent event) {
long id = Thread.currentThread().getId();
Log.d("onEventMainThread", "Thread id = " + id);
mTvShow.setText("onEvent : " + event.message);
}
  • 结果,线程ID相同

测试onEventMainThread

  • 测试接收者是在主线程
// Called in Android UI's main thread
public void onEventMainThread(MessageEvent event) {
long id = Thread.currentThread().getId();
Log.d("onEventMainThread", "Thread id = " + id);
mTvShow.setText("onEventMainThread : \n" + event.message);
}
  • 结果,接收者在主线程

测试onEventBackgroundThread

  • 测试发送者和接收者是在同一个线程
// Called in the background thread
public void onEventBackgroundThread(final MessageEvent event){
long id = Thread.currentThread().getId();
Log.d("onEventBackgroundThread", "Thread id = " + id);
runOnUiThread(new Runnable() {
@Override
public void run() {
mTvShow.setText("onEventBackgroundThread : " + event.message);
}
});
}
  • 结果,发送者和接收者是在同一个线程

测试onEventAsync

  • 测试发送者和接收者不是在同一个线程
// Called in a separate thread
public void onEventAsync(final MessageEvent event) {
long id = Thread.currentThread().getId();
Log.d("onEventAsync", "Thread id = " + id);
runOnUiThread(new Runnable() {
@Override
public void run() {
mTvShow.setText("onEventAsync : " + event.message);
}
});
}
  • 结果,发送者和接收者不是在同一个线程

EventBus详解的更多相关文章

  1. 【Android】事件总线(解耦组件) EventBus 详解

    当Android项目越来越庞大的时候,应用的各个部件之间的通信变得越来越复杂,例如:当某一条件发生时,应用中有几个部件对这个消息感兴趣,那么我们通常采用的就是观察者模式,使用观察者模式有一个弊病就是部 ...

  2. Android事件总线EventBus详解

    顾名思义,AndroidEventBus是一个Android平台的事件总线框架,它简化了Activity.Fragment.Service等组件之间的交互,很大程度上降低了它们之间的耦合,使我们的代码 ...

  3. android EventBus详解(三)

    post()方法调用流程 我们继续来看EventBus类,的另一个入口方法post() //已省略部分代码 public void post(Object event) { PostingThread ...

  4. android EventBus详解(二)

    上一节讲了EventBus的使用方法和实现的原理,下面说一下EventBus的Poster只对粘滞事件和invokeSubscriber()方法是怎么发送的. Subscribe流程 我们继续来看Ev ...

  5. android EventBus详解(一)

    EventBus 是一款针对Android优化的发布/订阅事件总线.主要功能是替代Intent, Handler, BroadCast 在 Fragment,Activity,Service,线程之间 ...

  6. Android消息传递之EventBus 3.0使用详解

    前言: 前面两篇不仅学习了子线程与UI主线程之间的通信方式,也学习了如何实现组件之间通信,基于前面的知识我们今天来分析一下EventBus是如何管理事件总线的,EventBus到底是不是最佳方案?学习 ...

  7. Android EventBus 3.0 实例使用详解

    EventBus的使用和原理在网上有很多的博客了,其中泓洋大哥和启舰写的非常非常棒,我也是跟着他们的博客学会的EventBus,因为是第一次接触并使用EventBus,所以我写的更多是如何使用,源码解 ...

  8. 安卓高级EventBus使用详解

    我本来想写但是在网上看了下感觉写得不如此作者写得好:http://www.jianshu.com/p/da9e193e8b03 前言:EventBus出来已经有一段时间了,github上面也有很多开源 ...

  9. EventBus (二) 使用详解——EventBus使用进阶

    相关文章: 1.<EventBus使用详解(一)——初步使用EventBus> 2.<EventBus使用详解(二)——EventBus使用进阶> 一.概述 前一篇给大家装简单 ...

随机推荐

  1. LruCache的缓存策略

    一.Android中的缓存策略 一般来说,缓存策略主要包含缓存的添加.获取和删除这三类操作.如何添加和获取缓存这个比较好理解,那么为什么还要删除缓存呢?这是因为不管是内存缓存还是硬盘缓存,它们的缓存大 ...

  2. [CQOI 2011]动态逆序对

    Description 题库链接 对于序列 \(A\) ,它的逆序对数定义为满足 \(i<j\) ,且 \(A_i>A_j\) 的数对 \((i,j)\) 的个数.给 \(1\) 到 \( ...

  3. hdu 5480(前缀和)

    题意:如果一个点,则这点的横竖皆被占领,询问矩阵是否全被占领. 思路:将被占领的x,y标记为1,用x表示1 - i的和 如果x轴的差为 x2 - x1 + 1则表示全被占领,y轴同理 #include ...

  4. [UOJ UNR #2]积劳成疾

    来自FallDream的博客,未经允许,请勿转载,谢谢. 传送门 区间最大值的题emmmm 想到构建笛卡尔树,这样自然就想到了一种dp f[i][j]表示大小为i的笛卡尔树,根的权值是j的答案. 转移 ...

  5. 习题9-8 Uva1632

    题意: 给你n个宝藏,然后给出他们的位置a[i]以及存在时间tim[i],如果能全部拿完,求出最短时间: 否则输出No solution 思路: 对于一段区间[i,j],你取完之后肯定是在最左端或者最 ...

  6. Excel实现双击插入当前日期时间

    用vba做一个事件驱动程序. 第一步:点击开发工具-visual basic. 第二步:在当前工作表中编制程序如下: Private Sub Worksheet_BeforeDoubleClick(B ...

  7. Prim算法的简单分析

    Prim算法主要的思路:将点集一分为二,通过找到两个点集之间的最短距离,来确定最小生成树,每次确定最短距离后,对两个点集进行更新. 具体的实现过程:难点就是如何找到两个点集之间的最短距离,这里设置两个 ...

  8. KMP算法小结

    最近看了一些关于KMP算法的资料,在此写一篇博客总计一下. 1.KMP算法介绍 KMP算法是一种字符串搜索的改进算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称 ...

  9. chrome下positon:fixed无效或抖动的解决办法

    先来看一下我们要实现的效果 我想这种效果大家都有实现过,或者说吸顶的效果和这差不多 页面结构 js代码如下 /*吸顶*/ var $child = $("#child_3"); v ...

  10. 独立完成一个移动点餐wap后的小结

    1.技术栈:vue  vue-router  vuex  Mint-ui  better-scroll; 2.实践总结: a.单页应用不重新渲染组件问题:组件在初次渲染后不会重新渲染,此时当从某个路径 ...