一、作用和特点
-
作用:在组件 / 线程间通信的场景中,将数据或事件传递给对应的订阅者。
-
特点:在 Android 组件 / 线程间通信的应用场景中,EventBus 比传统的接口监听、Handler、Executors、LocalBroadcastManager 更简洁可靠,具体描述如下:
-
使用事件总线框架,实现事件发布者与订阅者松耦合;
-
提供了透明线程间通信,隐藏了发布线程与订阅线程间的线程切换。
-
二、关键角色
-
Event:事件,它可以是任意类型(需定义)。
-
Subscriber:事件订阅者,事件处理的方法名可自定义,不过需要加上注解
@subscribe
,并且可指定线程模型和优先级,默认是POSTING
。 -
Publisher:事件的发布者,可以在任意线程里发布事件。一般情况下,使用
EventBus.getDefault()
就可以得到一个EventBus对象,然后再调用post(Object)
方法即可。
三、 事件订阅者
3.1、注册与注销EventBus
在发布事件之前,需要先 注册订阅者。而在订阅者生命周期结束时,需要 注销订阅者。注册与注销应保持在对称的生命周期。一般选择在Activity的onCreate()方法里去注册EventBus,在onDestory()方法里,去解除注册【EventBus持有订阅者的强引用,如果在订阅者被销毁时,没有注销,会导致内存泄漏】。
//注册
if(!EventBus.getDefault().isRegister(this)){
EventBus.getDefault().register(this);
}
//注销
if(EventBus.getDefault().isRegister(this)){
EventBus.getDefault().unregister(this);
}
3.2、四种线程模型
设置方式:@Subscribe(threadMode = ThreadMode.MAIN)
-
ThreadMode.POSTING:默认模式,订阅者发布的事件将会在所在的线程调用。时间的传递是同步的,一旦发布事件,所有对该模式的订阅事件都会执行。这种线程模式意味着最少的性能开销,因为它避免了线程的切换。因此,对于不要求是主线程并且耗时很短的简单任务推荐使用该模式。
-
ThreadMode.MAIN:订阅方法在主线程(UI)调用 ,因此可以直接更新 UI ,如果发布事件的线程是主线程,那么该模式的订阅者方法将被直接调用。
-
ThreadMode.MAIN_ORDERED:订阅方法在主线程(UI)调用,因此可以直接更新UI,事件将先进入队列然后才发送给订阅者,所以发布事件的调用将立即返回。这使得事件的处理保持严格的串行顺序。
-
ThreadMode.BACKGROUND:订阅者方法将在后台线程中被调用,如果发布事件的线程不是主线程,那么订阅者方法将会直接在该线程被调用。如果是主线程,那么将会使用一个单独的后台线程,该线程将按顺序发送所有的事件。
-
ThreadMode.ASYNC:订阅者方法将在一个单独的线程中被调用,发布事件的调用者将立即返回。如果订阅者方法的执行需要一些时间,例如网络访问,那么就应该使用该模式。避免触发大量的长时间运行的订阅者方法,以限制并发线程的数量。EventBus使用了一个线程池来有效地重用已经完成调用订阅者方法的线程。
注意:使用【1.2.3.4】模式的订阅者方法必须快速返回,以避免阻塞主线程。即订阅者方法执行需要耗时时,需选择【5】线程模式。【1.2.3】使用不当会导致丢帧,【4】使用不当会导致队首阻塞,【5】使用不当会导致内存抖动。
3.3、事件类型
设置方式:@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
1、基础事件(sticky = false,默认)
只有注册了,订阅者才能将接收到事件
2、粘性事件(sticky = true)
事件只要发送了,无论是在发送前注册还是发送后注册,订阅者都能收到事件,这就是粘性事件。
3.4、事件优先级
设置方式:@Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 1)
用来指定订阅方法的优先级,是一个整数类型的值,默认是0,值越大表示优先级越大。在同一传递线程(ThreadMode)中,较高优先级的订户将在优先级较低的其他订户之前接收事件。优先级不会影响具有不同ThreadModes的订阅者的传递顺序!
需要注意:
-
只有当两个订阅方法使用相同的
ThreadMode
参数的时候,它们的优先级才会与priority
指定的值一致; -
只有当某个订阅方法的
ThreadMode
参数为POSTING
的时候,它才能停止该事件的继续分发。取消事件传递:EventBus.getDefault().cancelEventDelivery(event) ;
四、编译时索引
默认情况下,EventBus 查找订阅者方法时采用的是反射,订阅者索引可以加速订阅者的注册,是一个可选的优化。其原理是:使用 EventBus 的注解处理器在应用构建期间创建订阅者索引类,该类包含了订阅者和订阅者方法的相关信息。EventBus 官方推荐在 Android 中使用订阅者索引以获得最佳的性能。要开启订阅者索引的生成,你需要在构建脚本中使用annotationProcessor属性将EventBus的注解处理器添加到应用的构建中,还要设置一个eventBusIndex参数来指定要生成的订阅者索引的完全限定类名。
索引优化就是索引优化,它有两种实现方式:手动设置索引和自动设置索引。自动设置索引其实才是使用APT技术实现的。
//订阅者索引,在 android defaultConfig 中,加入如下:
//在defaultConfig中的代码作用是APT生成的文件名称及路径
javaCompileOptions {
annotationProcessorOptions {
arguments = [eventBusIndex: 'com.testdemo.www.eventbus.MainActivityIndex']
}
}
//最后加入
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
implementation "org.greenrobot:eventbus:3.2.0"
在自定义的 Application 中:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//配置EventBus
EventBus.builder().addIndex(new MainActivityIndex()).installDefaultEventBus();
}
}
五、eventBus的使用
1、引入EventBus
implementation "org.greenrobot:eventbus:3.2.0"
2、自定义EventMessage对象
public class EventMessage {
private int type;
private String message ;
public EventMessage(int type, String message) {
this.type = type;
this.message = message;
}
@Override
public String toString() {
return "type="+type+" message= "+message;
}
}
3、在订阅方法实现的类中,注册和注销EventBus,实现订阅方法
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@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);
}
//订阅方法
@Subscribe(threadMode = ThreadMode.POSTING ,sticky =true)
public void onMessage(EventMessage) {
Toast.makeText(this, "收到粘性事件", Toast.LENGTH_SHORT).show();
Log.e(TAG, "onMessagePosting(), current is " + Thread.currentThread().getName());
//移除粘性事件
EventBus.getDefault().removeStickyEvent(event);
}
}
4、在需要的地方,发送消息
//普通消息
EventBus.getDefault().post(new EventMessage(1,"Hello everyone!"));
//粘性消息
EventBus.getDefault().postSticky(new EventMessage(2,"Hello everyone!"));
六、LiveDataBus的使用
6.1、为什么要用LiveDataBus替代EventBus?
- LiveDataBus的实现及其简单,相对EventBus复杂的实现,LiveDataBus只需要一个类就可以实现。
- LiveDataBus可以减小APK包的大小,由于LiveDataBus只依赖Android官方Android Architecture Components组件的LiveData,没有其他依赖,本身实现只有一个类。作为比较,EventBus JAR包大小为57kb,使用LiveDataBus可以大大减小APK包的大小。
- LiveDataBus依赖方支持更好,LiveDataBus只依赖Android官方Android Architecture Components组件的LiveData,依赖方支持更好。
- LiveDataBus具有生命周期感知,LiveDataBus具有生命周期感知,在Android系统中使用调用者不需要调用反注册,相比EventBus使用更为方便,并且没有内存泄漏风险。
6.2 、LiveDataBus的组成
- 消息:消息可以是任何的Object,可以定义不同类型的消息,如Boolean、String。也可以定义自定义类型的消息。
- 消息通道:LiveData扮演了消息通道的角色,不同的消息通道用不同的名字区分,名字是String类型的,可以通过名字获取到一个LiveData消息通道。
- 消息总线:消息总线通过单例实现,不同的消息通道存放在一个HashMap中。
- 订阅:订阅者通过getChannel获取消息通道,然后调用observe订阅这个通道的消息。
- 发布:发布者通过getChannel获取消息通道,然后调用setValue或者postValue发布消息。
6.3、LiveDataBus的使用
public final class LiveDataBus {
private final Map<String, BusMutableLiveData<Object>> bus;
private static volatile LiveDataBus mLiveDataBus;
private LiveDataBus() {
bus = new HashMap<>();
}
public static LiveDataBus getInstance() {
if (mLiveDataBus == null) {
synchronized (LiveDataBus.class) {
if (mLiveDataBus == null) {
mLiveDataBus = new LiveDataBus();
}
}
}
return mLiveDataBus;
}
public interface Observable<T> {
void post(T value);
void postDelay(T value, long delay);
void postDelay(T value, long delay, TimeUnit unit);
void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer);
void observeSticky(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer);
void observeForever(@NonNull Observer<? super T> observer);
void observeStickyForever(@NonNull Observer<T> observer);
void removeObserver(@NonNull Observer<? super T> observer);
}
private static class BusMutableLiveData<T> extends MutableLiveData<T> implements Observable<T> {
private class PostValueTask implements Runnable {
private Object newValue;
public PostValueTask(@NonNull Object newValue) {
this.newValue = newValue;
}
@Override
public void run() {
setValue((T) newValue);
}
}
@NonNull
private final String key;
private Map<Observer, Observer> observerMap = new HashMap<>();
private Handler mainHandler = new Handler(Looper.getMainLooper());
private BusMutableLiveData(String key) {
this.key = key;
}
private boolean isMainThread() {
return Looper.getMainLooper().getThread() == Thread.currentThread();
}
@Override
public void post(T value) {
if(isMainThread()) {
setValue(value);
} else {
mainHandler.post(new PostValueTask(value));
}
}
@Override
public void postDelay(T value, long delay) {
mainHandler.postDelayed(new PostValueTask(value), delay);
}
@Override
public void postDelay(T value, long delay, TimeUnit unit) {
postDelay(value, TimeUnit.MILLISECONDS.convert(delay, unit));
}
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
SafeCastObserver<T> safeCastObserver = new SafeCastObserver(observer);
//保存LifecycleOwner的当前状态
Lifecycle lifecycle = owner.getLifecycle();
Lifecycle.State currentState = lifecycle.getCurrentState();
int observerSize = getLifecycleObserverMapSize(lifecycle);
boolean needChangeState = currentState.isAtLeast(Lifecycle.State.STARTED);
if (needChangeState) {
//把LifecycleOwner的状态改为INITIALIZED
setLifecycleState(lifecycle, Lifecycle.State.INITIALIZED);
//set observerSize to -1,否则super.observe(owner, observer)的时候会无限循环
setLifecycleObserverMapSize(lifecycle, -1);
}
super.observe(owner, safeCastObserver);
if (needChangeState) {
//重置LifecycleOwner的状态
setLifecycleState(lifecycle, currentState);
//重置observer size,因为又添加了一个observer,所以数量+1
setLifecycleObserverMapSize(lifecycle, observerSize + 1);
//把Observer置为active
hookObserverActive(safeCastObserver, true);
}
//更改Observer的version
hookObserverVersion(safeCastObserver);
}
public void observeSticky(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
super.observe(owner, new SafeCastObserver<>(observer));
}
@Override
public void observeForever(@NonNull Observer<? super T> observer) {
if (!observerMap.containsKey(observer)) {
observerMap.put(observer, new ObserverWrapper(observer));
}
super.observeForever(observerMap.get(observer));
}
public void observeStickyForever(@NonNull Observer<T> observer) {
super.observeForever(observer);
}
@Override
public void removeObserver(@NonNull Observer<? super T> observer) {
Observer realObserver;
if (observerMap.containsKey(observer)) {
realObserver = observerMap.remove(observer);
} else {
realObserver = observer;
}
super.removeObserver(realObserver);
if (!hasObservers()) {
LiveDataBus.getInstance().bus.remove(key);
}
}
private int getLifecycleObserverMapSize(Lifecycle lifecycle) {
if (lifecycle == null) {
return 0;
}
if (!(lifecycle instanceof LifecycleRegistry)) {
return 0;
}
try {
Field observerMapField = LifecycleRegistry.class.getDeclaredField("mObserverMap");
observerMapField.setAccessible(true);
Object mObserverMap = observerMapField.get(lifecycle);
Class<?> superclass = mObserverMap.getClass().getSuperclass();
Field mSizeField = superclass.getDeclaredField("mSize");
mSizeField.setAccessible(true);
return (int) mSizeField.get(mObserverMap);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
private void setLifecycleState(Lifecycle lifecycle, Lifecycle.State state) {
if (lifecycle == null) {
return;
}
if (!(lifecycle instanceof LifecycleRegistry)) {
return;
}
try {
Field mState = LifecycleRegistry.class.getDeclaredField("mState");
mState.setAccessible(true);
mState.set(lifecycle, state);
} catch (Exception e) {
e.printStackTrace();
}
}
private void setLifecycleObserverMapSize(Lifecycle lifecycle, int size) {
if (lifecycle == null) {
return;
}
if (!(lifecycle instanceof LifecycleRegistry)) {
return;
}
try {
Field observerMapField = LifecycleRegistry.class.getDeclaredField("mObserverMap");
observerMapField.setAccessible(true);
Object mObserverMap = observerMapField.get(lifecycle);
Class<?> superclass = mObserverMap.getClass().getSuperclass();
Field mSizeField = superclass.getDeclaredField("mSize");
mSizeField.setAccessible(true);
mSizeField.set(mObserverMap, size);
} catch (Exception e) {
e.printStackTrace();
}
}
private Object getObserverWrapper(@NonNull Observer<T> observer) throws Exception {
Field fieldObservers = LiveData.class.getDeclaredField("mObservers");
fieldObservers.setAccessible(true);
Object objectObservers = fieldObservers.get(this);
Class<?> classObservers = objectObservers.getClass();
Method methodGet = classObservers.getDeclaredMethod("get", Object.class);
methodGet.setAccessible(true);
Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);
Object objectWrapper = null;
if (objectWrapperEntry instanceof Map.Entry) {
objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();
}
return objectWrapper;
}
private void hookObserverActive(@NonNull Observer<T> observer, boolean active) {
try {
Object objectWrapper = getObserverWrapper(observer);
if (objectWrapper != null) {
Class<?> classObserverWrapper = objectWrapper.getClass().getSuperclass();
Field mActive = classObserverWrapper.getDeclaredField("mActive");
mActive.setAccessible(true);
mActive.set(objectWrapper, active);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void hookObserverVersion(@NonNull Observer<T> observer) {
try {
Object objectWrapper = getObserverWrapper(observer);
if (objectWrapper != null) {
Class<?> classObserverWrapper = objectWrapper.getClass().getSuperclass();
Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");
fieldLastVersion.setAccessible(true);
//get livedata's version
Field fieldVersion = LiveData.class.getDeclaredField("mVersion");
fieldVersion.setAccessible(true);
Object objectVersion = fieldVersion.get(this);
//set wrapper's version
fieldLastVersion.set(objectWrapper, objectVersion);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static class ObserverWrapper<T> implements Observer<T> {
@NonNull
private final Observer<T> observer;
ObserverWrapper(@NonNull Observer<T> observer) {
this.observer = observer;
}
@Override
public void onChanged(@Nullable T t) {
if (isCallOnObserve()) {
return;
}
try {
observer.onChanged(t);
} catch (ClassCastException e) {
e.printStackTrace();
}
}
private boolean isCallOnObserve() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
if (stackTrace != null && stackTrace.length > 0) {
for (StackTraceElement element : stackTrace) {
if ("androidx.lifecycle.LiveData".equals(element.getClassName()) &&
"observeForever".equals(element.getMethodName())) {
return true;
}
}
}
return false;
}
}
private static class SafeCastObserver<T> implements Observer<T> {
@NonNull
private final Observer<T> observer;
SafeCastObserver(@NonNull Observer<T> observer) {
this.observer = observer;
}
@Override
public void onChanged(@Nullable T t) {
try {
observer.onChanged(t);
} catch (ClassCastException e) {
e.printStackTrace();
}
}
}
public synchronized <T> Observable<T> with(String key, Class<T> type) {
if (!bus.containsKey(key)) {
bus.put(key, new BusMutableLiveData<>(key));
}
return (Observable<T>) bus.get(key);
}
}
注册订阅:
LiveDataBus.getInstance().with("string", String.class)
.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d(TAG, "onChanged: " + s);
}
});
发送消息:
LiveDataBus.getInstance().with("string", String.class).post("string");
本篇文章结合其他博主分享整合而成,又加入自己的理解,如有错误,欢迎大家留言!