Android EventBus 3.0.0 使用总结(必看篇)

作者:jingxian 时间:2023-09-06 06:32:41 

前言

EventBus框架

EventBus是一个通用的叫法,例如Google出品的Guava,Guava是一个庞大的库,EventBus只是它附带的一个小功能,因此实际项目中使用并不多。用的最多的是greenrobot/EventBus,这个库的优点是接口简洁,集成方便,但是限定了方法名,不支持注解。另一个库square/otto修改自 Guava ,用的人也不少。所以今天我们研究的目标是greenrobot的EventBus.

EventBus 简介

1、EventBus3.0.0 是最新的版本。
2、EventBus 是Android 发布/订阅事件总线,可简化 Activities, Fragments, Threads, Services 等组件间的消息传递。
3、可替代 Intent, Handler, BroadCast ,接口等传统方案,更快,代码更小,50K 左右的 jar 包,代码更优雅,彻底解耦。

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

EventBus原理图

Android EventBus 3.0.0 使用总结(必看篇)

如何添加依赖

在module的build.gredle 文件中的dependencies标签中添加

compile 'org.greenrobot:eventbus:3.0.0'

例如


apply plugin: 'com.android.application'

android {
 compileSdkVersion 24
 buildToolsVersion "24.0.3"

defaultConfig {
   applicationId "com.eventbus.app"
   minSdkVersion 14
   targetSdkVersion 24
   versionCode 1
   versionName "1.0"

}
 buildTypes {
   release {
     minifyEnabled false
     proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
   }
 }
}

dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 compile 'com.android.support:appcompat-v7:24.2.1'

compile 'org.greenrobot:eventbus:3.0.0'
}

如何使用

注册事件

EventBus.getDefault().register( this );

取消注册

EventBus.getDefault().unregister( this );

发送数据

EventBus.getDefault().post( "我发射了");

简单小例子:使用EventBus传递简单字符串


package com.eventbus.app;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity {

@Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

//注册
   EventBus.getDefault().register( this );

findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
       EventBus.getDefault().post( "我发射了");
     }
   });
 }

/**
  * 自定义一个方法 hello() ,用来接收事件。
  * 方法名字可以随便写
  * @return
  */

@Subscribe(threadMode = ThreadMode.MAIN)
 public void hello ( String event){
   /* Do something */
   Toast.makeText( this , event , Toast.LENGTH_SHORT).show();
 };

@Override
 protected void onDestroy() {
   super.onDestroy();

//取消注册 , 防止Activity内存泄漏
   EventBus.getDefault().unregister( this );
 }
}

线程模型

在接收事件消息的方法中,可以通过注解的方式设置线程模型,EventBus内置了4中线程模型,分别是ThreadMode.POSTING 、ThreadMode.MAIN、ThreadMode.BACKGROUND、ThreadMode.ASYNC

比如:


@Subscribe(threadMode = ThreadMode.POSTING)
 public void onMessageEventPostThread(String event) {
   Log.e( "event PostThread", "消息: " + event + " thread: " + Thread.currentThread().getName() );
 }

@Subscribe(threadMode = ThreadMode.MAIN)
 public void onMessageEventMainThread(String event) {
   Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
 }

@Subscribe(threadMode = ThreadMode.BACKGROUND)
 public void onMessageEventBackgroundThread(String event) {
   Log.e( "event BackgroundThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
 }

@Subscribe(threadMode = ThreadMode.ASYNC)
 public void onMessageEventAsync(String event) {
   Log.e( "event Async", "消息: " + event + " thread: " + Thread.currentThread().getName());
 }

PostThread:如果使用事件处理函数指定了线程模型为PostThread,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为PostThread的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。

MainThread:如果使用事件处理函数指定了线程模型为MainThread,那么不论事件是在哪个线程中发布出来的,该事件处理函数都会在UI线程中执行。该方法可以用来更新UI,但是不能处理耗时操作。

BackgroundThread:如果使用事件处理函数指定了线程模型为BackgroundThread,那么如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。

Async:如果使用事件处理函数指定了线程模型为Async,那么无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行。同样,此事件处理函数中禁止进行UI更新操作。

小例子1: 在子线程发送数据


package com.eventbus.app;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity {

@Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

//注册
   EventBus.getDefault().register( this );

findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
       new Thread(new Runnable() {
         @Override
         public void run() {
           Log.d( "event 发射数据线程 : " , Thread.currentThread().getName() ) ;
           EventBus.getDefault().post( "我发射了");
         }
       }).start() ;
     }
   });
 }

@Subscribe(threadMode = ThreadMode.POSTING)
 public void onMessageEventPostThread(String event) {
   Log.e( "event PostThread", "消息: " + event + " thread: " + Thread.currentThread().getName() );
 }

@Subscribe(threadMode = ThreadMode.MAIN)
 public void onMessageEventMainThread(String event) {
   Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
 }

@Subscribe(threadMode = ThreadMode.BACKGROUND)
 public void onMessageEventBackgroundThread(String event) {
   Log.e( "event BackgroundThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
 }

@Subscribe(threadMode = ThreadMode.ASYNC)
 public void onMessageEventAsync(String event) {
   Log.e( "event Async", "消息: " + event + " thread: " + Thread.currentThread().getName());
 }

@Override
 protected void onDestroy() {
   super.onDestroy();

//取消注册 , 防止Activity内存泄漏
   EventBus.getDefault().unregister( this );
 }
}

运行结果:

D/event 发射数据线程 :: Thread-109
E/event BackgroundThread: 消息: 我发射了 thread: Thread-109
E/event PostThread: 消息: 我发射了 thread: Thread-109
E/event Async: 消息: 我发射了 thread: pool-1-thread-2
E/event MainThread: 消息: 我发射了 thread: main

小例子2: 在主线程发送数据


package com.eventbus.app;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity {

@Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

//注册
   EventBus.getDefault().register( this );

findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
       Log.d( "event 发射数据线程 : " , Thread.currentThread().getName() ) ;
       EventBus.getDefault().post( "我发射了");
     }
   });
 }

@Subscribe(threadMode = ThreadMode.POSTING)
 public void onMessageEventPostThread(String event) {
   Log.e( "event PostThread", "消息: " + event + " thread: " + Thread.currentThread().getName() );
 }

@Subscribe(threadMode = ThreadMode.MAIN)
 public void onMessageEventMainThread(String event) {
   Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
 }

@Subscribe(threadMode = ThreadMode.BACKGROUND)
 public void onMessageEventBackgroundThread(String event) {
   Log.e( "event BackgroundThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
 }

@Subscribe(threadMode = ThreadMode.ASYNC)
 public void onMessageEventAsync(String event) {
   Log.e( "event Async", "消息: " + event + " thread: " + Thread.currentThread().getName());
 }

@Override
 protected void onDestroy() {
   super.onDestroy();

//取消注册 , 防止Activity内存泄漏
   EventBus.getDefault().unregister( this );
 }
}

运行结果:

D/event 发射数据线程 :: main
E/event MainThread: 消息: 我发射了 thread: main
E/event PostThread: 消息: 我发射了 thread: main
E/event Async: 消息: 我发射了 thread: pool-1-thread-3
E/event BackgroundThread: 消息: 我发射了 thread: pool-1-thread-4

黏性事件

除了上面讲的普通事件外,EventBus还支持发送黏性事件。何为黏性事件呢?简单讲,就是在发送事件之后再订阅该事件也能收到该事件,跟黏性广播类似。具体用法如下:

注册

EventBus.getDefault().register( this );

事件接收


@Subscribe(threadMode = ThreadMode.MAIN , sticky = true )
public void onMessageEventMainThread(String event) {
Log.e( "event MainThread", "消息: " + event + " thread: " + > Thread.currentThread().getName());
}

取消注册

EventBus.getDefault().unregister( this ) ;

发送事件

EventBus.getDefault().postSticky( "我发射了");

小例子:在MainActivity发送事件,在Activity2里注册并且接收事件

MainActivity源码


package com.eventbus.app;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import org.greenrobot.eventbus.EventBus;

public class MainActivity extends AppCompatActivity {

@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) {
       Log.d( "event 发射数据线程 : " , Thread.currentThread().getName() ) ;
       EventBus.getDefault().postSticky( "我发射了");

startActivity( new Intent( MainActivity.this , Activity2.class ));
     }
   });
 }
}

Activity2源码


package com.eventbus.app;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class Activity2 extends AppCompatActivity {

@Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_2);
   //注册
   EventBus.getDefault().register( this );
 }

@Subscribe(threadMode = ThreadMode.MAIN , sticky = true )
 public void onMessageEventMainThread(String event) {
   Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
 }

@Override
 protected void onDestroy() {
   super.onDestroy();
   //取消注册 , 防止Activity内存泄漏
   EventBus.getDefault().unregister( this ) ;
 }
}

这就是粘性事件,能够收到订阅之前发送的消息。但是它只能收到最新的一次消息,比如说在未订阅之前已经发送了多条黏性消息了,然后再订阅只能收到最近的一条消息。

EventBus源码分析

Subscribe 接口源码


@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
 ThreadMode threadMode() default ThreadMode.POSTING;

/**
  * If true, delivers the most recent sticky event (posted with
  * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
  */
 boolean sticky() default false;

/** Subscriber priority to influence the order of event delivery.
  * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
  * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
  * delivery among subscribers with different {@link ThreadMode}s! */
 int priority() default 0;
}

可以看出默认的线程模型是ThreadMode.POSTING ;默认黏性事件为false,也就是默认不开启黏性事件;默认的优选级为0 。

EventBus 类部分源码


static volatile EventBus defaultInstance;

/** 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() 是一个单例模式 , 只有一个实例对象。

ThreadMode 类源码


public enum ThreadMode {

/**
  * 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 must return quickly to avoid blocking the posting thread, which may be the main thread.
  */

POSTING,

/**
  * 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.
  */

MAIN,

/**
  * 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.
  */

BACKGROUND,

/**
  * 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.
  */

ASYNC
}

这个类是枚举类,定义了线程模型中的几种类型。

标签:android,eventbus3.0,使用
0
投稿

猜你喜欢

  • C# MVC 微信支付教程系列之公众号支付代码

    2022-11-29 09:14:29
  • Java日常练习题,每天进步一点点(46)

    2023-10-05 11:20:29
  • JAVA实现将磁盘中所有空文件夹进行删除的代码

    2022-09-01 04:59:41
  • android scrollview 滑动到顶端或者指定位置的实现方法

    2022-04-27 00:12:40
  • C# Winform使用扩展方法实现自定义富文本框(RichTextBox)字体颜色

    2021-06-23 15:05:50
  • Android编程中的消息机制实例详解

    2022-11-14 06:50:05
  • spring boot RestTemplate 发送get请求的踩坑及解决

    2022-01-19 16:08:09
  • 实例详解用户输入 i. 检测常用手势

    2022-04-10 19:22:55
  • java和matlab画多边形闭合折线图示例讲解

    2021-06-23 08:39:15
  • C# WebApi 接口返回值不困惑:返回值类型详解

    2022-05-06 13:16:35
  • android实现文本复制到剪切板功能(ClipboardManager)

    2023-11-28 17:40:31
  • Java多线程编程之读写锁ReadWriteLock用法实例

    2021-10-13 17:01:14
  • Android编程之在SD卡上进行文件读写操作实例详解

    2022-04-15 10:29:50
  • Android 动画之RotateAnimation应用详解

    2022-08-17 17:03:07
  • Android组件必学之TabHost使用方法详解

    2021-11-12 04:56:47
  • android仿支付宝、微信密码输入框效果

    2021-12-23 12:59:16
  • c# 如何将字符串转换为大写或小写

    2023-01-04 20:44:28
  • JetBrains IntelliJ IDEA 配置优化技巧

    2022-06-19 08:31:38
  • C# Distinct和重写IEqualityComparer时要知道的二三事

    2023-07-11 15:41:20
  • java多线程通过CompletableFuture组装异步计算单元

    2023-07-19 10:15:42
  • asp之家 软件编程 m.aspxhome.com