Android EventBus 3.0.0 使用總結(jié)(必看篇)
前言
EventBus框架
EventBus是一個(gè)通用的叫法,例如Google出品的Guava,Guava是一個(gè)龐大的庫(kù),EventBus只是它附帶的一個(gè)小功能,因此實(shí)際項(xiàng)目中使用并不多。用的最多的是greenrobot/EventBus,這個(gè)庫(kù)的優(yōu)點(diǎn)是接口簡(jiǎn)潔,集成方便,但是限定了方法名,不支持注解。另一個(gè)庫(kù)square/otto修改自 Guava ,用的人也不少。所以今天我們研究的目標(biāo)是greenrobot的EventBus.
EventBus 簡(jiǎn)介
1、EventBus3.0.0 是最新的版本。
2、EventBus 是Android 發(fā)布/訂閱事件總線,可簡(jiǎn)化 Activities, Fragments, Threads, Services 等組件間的消息傳遞。
3、可替代 Intent, Handler, BroadCast ,接口等傳統(tǒng)方案,更快,代碼更小,50K 左右的 jar 包,代碼更優(yōu)雅,徹底解耦。
github地址:https://github.com/greenrobot/EventBus
EventBus原理圖

如何添加依賴
在module的build.gredle 文件中的dependencies標(biāo)簽中添加
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'
}
如何使用
注冊(cè)事件
EventBus.getDefault().register( this );
取消注冊(cè)
EventBus.getDefault().unregister( this );
發(fā)送數(shù)據(jù)
EventBus.getDefault().post( "我發(fā)射了");
簡(jiǎn)單小例子:使用EventBus傳遞簡(jiǎn)單字符串
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);
//注冊(cè)
EventBus.getDefault().register( this );
findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post( "我發(fā)射了");
}
});
}
/**
* 自定義一個(gè)方法 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();
//取消注冊(cè) , 防止Activity內(nèi)存泄漏
EventBus.getDefault().unregister( this );
}
}
線程模型
在接收事件消息的方法中,可以通過注解的方式設(shè)置線程模型,EventBus內(nèi)置了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:如果使用事件處理函數(shù)指定了線程模型為PostThread,那么該事件在哪個(gè)線程發(fā)布出來的,事件處理函數(shù)就會(huì)在這個(gè)線程中運(yùn)行,也就是說發(fā)布事件和接收事件在同一個(gè)線程。在線程模型為PostThread的事件處理函數(shù)中盡量避免執(zhí)行耗時(shí)操作,因?yàn)樗鼤?huì)阻塞事件的傳遞,甚至有可能會(huì)引起ANR。
MainThread:如果使用事件處理函數(shù)指定了線程模型為MainThread,那么不論事件是在哪個(gè)線程中發(fā)布出來的,該事件處理函數(shù)都會(huì)在UI線程中執(zhí)行。該方法可以用來更新UI,但是不能處理耗時(shí)操作。
BackgroundThread:如果使用事件處理函數(shù)指定了線程模型為BackgroundThread,那么如果事件是在UI線程中發(fā)布出來的,那么該事件處理函數(shù)就會(huì)在新的線程中運(yùn)行,如果事件本來就是子線程中發(fā)布出來的,那么該事件處理函數(shù)直接在發(fā)布事件的線程中執(zhí)行。在此事件處理函數(shù)中禁止進(jìn)行UI更新操作。
Async:如果使用事件處理函數(shù)指定了線程模型為Async,那么無論事件在哪個(gè)線程發(fā)布,該事件處理函數(shù)都會(huì)在新建的子線程中執(zhí)行。同樣,此事件處理函數(shù)中禁止進(jìn)行UI更新操作。
小例子1: 在子線程發(fā)送數(shù)據(jù)
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);
//注冊(cè)
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 發(fā)射數(shù)據(jù)線程 : " , Thread.currentThread().getName() ) ;
EventBus.getDefault().post( "我發(fā)射了");
}
}).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();
//取消注冊(cè) , 防止Activity內(nèi)存泄漏
EventBus.getDefault().unregister( this );
}
}
運(yùn)行結(jié)果:
D/event 發(fā)射數(shù)據(jù)線程 :: Thread-109
E/event BackgroundThread: 消息: 我發(fā)射了 thread: Thread-109
E/event PostThread: 消息: 我發(fā)射了 thread: Thread-109
E/event Async: 消息: 我發(fā)射了 thread: pool-1-thread-2
E/event MainThread: 消息: 我發(fā)射了 thread: main
小例子2: 在主線程發(fā)送數(shù)據(jù)
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);
//注冊(cè)
EventBus.getDefault().register( this );
findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d( "event 發(fā)射數(shù)據(jù)線程 : " , Thread.currentThread().getName() ) ;
EventBus.getDefault().post( "我發(fā)射了");
}
});
}
@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();
//取消注冊(cè) , 防止Activity內(nèi)存泄漏
EventBus.getDefault().unregister( this );
}
}
運(yùn)行結(jié)果:
D/event 發(fā)射數(shù)據(jù)線程 :: main
E/event MainThread: 消息: 我發(fā)射了 thread: main
E/event PostThread: 消息: 我發(fā)射了 thread: main
E/event Async: 消息: 我發(fā)射了 thread: pool-1-thread-3
E/event BackgroundThread: 消息: 我發(fā)射了 thread: pool-1-thread-4
黏性事件
除了上面講的普通事件外,EventBus還支持發(fā)送黏性事件。何為黏性事件呢?簡(jiǎn)單講,就是在發(fā)送事件之后再訂閱該事件也能收到該事件,跟黏性廣播類似。具體用法如下:
注冊(cè)
EventBus.getDefault().register( this );
事件接收
@Subscribe(threadMode = ThreadMode.MAIN , sticky = true )
public void onMessageEventMainThread(String event) {
Log.e( "event MainThread", "消息: " + event + " thread: " + > Thread.currentThread().getName());
}
取消注冊(cè)
EventBus.getDefault().unregister( this ) ;
發(fā)送事件
EventBus.getDefault().postSticky( "我發(fā)射了");
小例子:在MainActivity發(fā)送事件,在Activity2里注冊(cè)并且接收事件
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 發(fā)射數(shù)據(jù)線程 : " , Thread.currentThread().getName() ) ;
EventBus.getDefault().postSticky( "我發(fā)射了");
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);
//注冊(cè)
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();
//取消注冊(cè) , 防止Activity內(nèi)存泄漏
EventBus.getDefault().unregister( this ) ;
}
}
這就是粘性事件,能夠收到訂閱之前發(fā)送的消息。但是它只能收到最新的一次消息,比如說在未訂閱之前已經(jīng)發(fā)送了多條黏性消息了,然后再訂閱只能收到最近的一條消息。
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;
}
可以看出默認(rèn)的線程模型是ThreadMode.POSTING ;默認(rèn)黏性事件為false,也就是默認(rèn)不開啟黏性事件;默認(rèn)的優(yōu)選級(jí)為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() 是一個(gè)單例模式 , 只有一個(gè)實(shí)例對(duì)象。
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
}
這個(gè)類是枚舉類,定義了線程模型中的幾種類型。
以上這篇Android EventBus 3.0.0 使用總結(jié)(必看篇)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Android?Jetpack庫(kù)剖析之LiveData組件篇
LiveData是Jetpack組件的一部分,更多的時(shí)候是搭配ViewModel來使用,相對(duì)于Observable,LiveData的最大優(yōu)勢(shì)是其具有生命感知的,換句話說,LiveData可以保證只有在組件( Activity、Fragment、Service)處于活動(dòng)生命周期狀態(tài)的時(shí)候才會(huì)更新數(shù)據(jù)2022-07-07
android實(shí)現(xiàn)上下左右滑動(dòng)界面布局
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)上下左右滑動(dòng)的界面布局,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12
Android開發(fā)中的文件操作工具類FileUtil完整實(shí)例
這篇文章主要介紹了Android開發(fā)中的文件操作工具類FileUtil,結(jié)合完整實(shí)例形式分析了Android文件操作的常用技巧,包括文件的獲取、遍歷、搜索、復(fù)制、刪除、判斷等功能,需要的朋友可以參考下2017-11-11

