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

如需转载请注明出处:Android EventBus 3.0 实例使用详解

一、概述

EventBus是一款Android下的发布/订阅事件总线机制。可以代替Intent、Handler、Broadcast等在Fragment、Activity之间传递消息。
优点:开销小,代码优雅。将发送者和接受者解耦。
既然是有关于事件的发布和订阅,那么发布者和订阅者的关系又是怎样的呢?
事件的发布者可以发布多个事件,发布者同时也可以是订阅者,订阅者可以订阅多个事件。
二、实例
接下来要通过实例来讲解如何使用EventBus了,在看代码之前要记得三个问题。
1、事件发布者如何发布事件
2、事件订阅者如何订阅事件
3、订阅者如何准确接收发布者发布的多个事件中的一个(假设发布者发布多个事件,订阅者只是订阅其中的一个事件)
(1)首先在gradle文件中添加EventBus的依赖
compile 'org.greenrobot:eventbus:3.0.0'

(2)在相关Activity中的onCreat()、onDestory()注册和解注EventBus

@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);
}

(3)事件发布者如何发布事件

EventBus.getDefault().post(实参);

我们到.getDefault()来看一个这个方法:

/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}

这里的.getDefault()方法其实就是一个单例,获取到EventBus实例后调用post方法开始发布事件

post():

/** Posts the given event to the event bus. */
public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event); if (!postingState.isPosting) {
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}

通过源码可以看得出来,方法的实参是一个对象类型的参数,参数会统一存储在eventQueue这个队列中,然后循环队列,将队列中的消息逐一发布,这里大家可能会想,每次post都会去调用整个队列么,那么不会造成方法多次调用么?

答案是不会的,因为在最外层加了一个判断,判断event是否被发布过,如果被发布过,则不会进入到这个方法内。

(4)事件订阅者订阅事件

@Subscribe
public void onEventMainThread(实参){
//接收到发布者发布的事件后,进行相应的处理操作
}

这里要注意的是:EventBus在 3.0 版本后,事件订阅监听的方法名可以随意起,不同于旧版本,名字是特定的。

public void onEventMainThread(param)
{
   //如果使用onEventMainThread作为订阅函数,那么不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,
   //这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。
} public void onEventPostThread(param)
{
//如果使用onEvent作为订阅函数,那么该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。
   //使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。
} public void onEventBackgroundThread(param)
{
//如果使用onEventBackgrond作为订阅函数,那么如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。
} public void onEventAsync(param)
{
  //使用这个函数作为订阅函数,那么无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync.
}

但是新版本需要手动的添加注解@Subscribe(这是必不可少的)。既然名字可以随意起,那么又怎么控制在什么线程内进行处理呢?

@Subscribe(threadMode = ThreadMode.MAIN)

给注解设置ThreadMode就可以了。

(5)事件发布者和订阅者如何对应上

可以看到发布事件和订阅事件,都需要传入一个实参,而且在post方法中我们也看到了,这个实参是对象类型的,大家猜想的话也可以知道,发布和订阅事件是通过一个对象实参来进行关联的。

public class TestEvent {
private int mMsg;
public TestEvent(int msg) {
mMsg = msg;
}
public int getMsg(){
return mMsg;
}
}

这个类很简单,只有一个变量和一个构造方法、get方法。具体内容根据项目需求来定。

基本上了解这些就可以搞明白EventBus的使用了,下面上一下我写的Demo,功能很简单,就是模仿下载的进度条,因为现在用的最多的是通过handler来进行处理的,而EventBus的出现,可以完美的代替handler,

而且实现了解耦。

好,上代码!

MainActivity.class

package com.example.wgh.eventbusdemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode; public class MainActivity extends Activity { public ProgressBar progressBar = null;
public int time = ;
@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<){
time += ;
EventBus.getDefault().post(new TestEvent(time));
try {
Thread.sleep();
} 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());
}
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.wgh.eventbusdemo.MainActivity"
android:orientation="vertical"> <ProgressBar
android:id="@+id/progressbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="150dp"
android:max=""
style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>
<Button
android:id="@+id/button"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始下载"/>
</LinearLayout>

TestEvent.class

public class TestEvent {
private int mMsg;
public TestEvent(int msg) {
mMsg = msg;
}
public int getMsg(){
return mMsg;
}
}

补充知识点:粘性事件

public class SecondActivity extends Activity {
private TextView textView = null; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
textView = (TextView) findViewById(R.id.test);
EventBus.getDefault().register(this);
} @Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
} @Subscribe(threadMode = ThreadMode.MAIN)
public void wgh2(TestEvent event){
textView.setText("同样接收到了msg"+event.getMsg());
}
}

发现SecondActivity中没有订阅到发布的事件,查了下资料才知道,在MainActivity中发布了事件,但是到了SecondActivity中没有订阅到,这里就需要用到粘性事件了

所谓粘性事件指的就是事件发布之后再订阅该事件,仍然可以收到该事件,这部分与普通事件的区别是:普通事件是先注册再绑定

所以代码方面就需要做一下调整

MainActivity:

EventBus.getDefault().postSticky(new TestEvent(time));

SecondActivity:

@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void wgh2(TestEvent event){
textView.setText("同样接收到了msg"+event.getMsg());
}

经过试验之后发现就生效了!!!

Android EventBus 3.0 实例使用详解的更多相关文章

  1. Android EventBus 3.0.0 使用总结

    转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6039221.html 本文出自[赵彦军的博客] 前言 EventBus框架 EventBus是一个通用的叫法 ...

  2. RxJava2.0的使用详解

    RxJava2.0的使用详解 1,初识RxJava RxJava就是一种用Java语言实现的响应式编程,来创建基于事件的异步程序 RxJava是一个基于事件订阅的异步执行的一个类库,目前比较火的一些技 ...

  3. Android 多线程之IntentService 完全详解

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

  4. Android 多线程之HandlerThread 完全详解

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

  5. Java经典设计模式之十一种行为型模式(附实例和详解)

    Java经典设计模式共有21中,分为三大类:创建型模式(5种).结构型模式(7种)和行为型模式(11种). 本文主要讲行为型模式,创建型模式和结构型模式可以看博主的另外两篇文章:Java经典设计模式之 ...

  6. Java经典设计模式之七大结构型模式(附实例和详解)

    博主在大三的时候有上过设计模式这一门课,但是当时很多都基本没有听懂,重点是也没有细听,因为觉得没什么卵用,硬是要搞那么复杂干嘛.因此设计模式建议工作半年以上的猿友阅读起来才会理解的比较深刻.当然,你没 ...

  7. Android开发:文本控件详解——TextView(一)基本属性

    一.简单实例: 新建的Android项目初始自带的Hello World!其实就是一个TextView. 在activity_main.xml中可以新建TextView,从左侧组件里拖拽到右侧预览界面 ...

  8. [置顶] xamarin android toolbar(踩坑完全入门详解)

    网上关于toolbar的教程有很多,很多新手,在使用toolbar的时候踩坑实在太多了,不好好总结一下,实在浪费.如果你想学习toolbar,你肯定会去去搜索androd toolbar,既然你能看到 ...

  9. Android 应用程序之间内容分享详解(二)

    转载请注明出处:http://blog.csdn.net/xiaanming/article/details/9428613 Android 应用程序之间内容分享详解(一) 之前给大家分享了你开发的应 ...

随机推荐

  1. [iOS]使用signal让app能够在从容崩溃

    前言 虽然大家都不愿意看到程序崩溃,但可能崩溃是每个应用必须面对的现实,既然崩溃已经发生,无法阻挡了,那我们就让它崩也崩得淡定点吧. iOS SDK中提供了一个现成的函数 NSSetUncaughtE ...

  2. js div截取字符串的长度

    <div style="width:100%;" id="changdu">这个是字符串的长度</div> $("#chang ...

  3. iOS 发布流程 分类: ios相关 app相关 2015-05-22 14:50 186人阅读 评论(0) 收藏

    1.登陆苹果开发者中心http://developer.apple.com(99美元账号) 2.进入itunes connect 3.选择Manage Your Apps 4.选择Add New Ap ...

  4. 两端对齐justify

    //容器设定text-align:justify.justify{ text-align: justify; } //容器里面的元素 .justify i{ width:24px; line-heig ...

  5. 使用getParameterMap()方法实现对请求参数的封装的工具类

    我们知道,HttpServletRequest这个类的getParameter(name),getParameterValues(name)可以分别实现对页面传来的单个参数和对多个同名参数的接受.特别 ...

  6. osgearth介绍(转载)-feature_labels.earth

    初识osg OSG的诞生 在 1997 年时,Don Burns 由于喜欢滑翔机运动且对计算机图形学非常熟悉,在 LINUX 上写了一个控制滑翔机的小引擎,这便是 OSG 的最初雏形.后来在 1998 ...

  7. java_web学习(15)jQuery

    JavaScript 库作用及对比 为了简化 JavaScript 的开发, 一些 JavsScript 库诞生了. JavaScript 库封装了很多预定义的对象和实用函数.能帮助使用者建立有高难度 ...

  8. 对js原型对象的拓展和原型对象的重指向的区别的研究

    我写了如下两段代码: function Person(){} var p1 = new Person(); Person.prototype = { constructor: Person, name ...

  9. 使用原始XML资源——使用原始XML文件

    下面为示例程序添加一个原始的XML文件,将该XML文件放到/res/xml目录下,该XML文件的内容很简单.XML资源的内容如下. 程序清单:  \res\xml\books.xml文件 <?x ...

  10. QT第六天学习

    基本事件: 鼠标事件 键盘事件 绘制事件 1.QT中的事件: 事件是对各应用程序需要知道的由应用程序内部或外部产生的事情或动作的通称. QT中事件的处理: 在QT中使用一个对象来表示一个事件,继承自Q ...