Android组件化架构 – 2. 组件间通信机制(2)

事件总线

  • 组件化层级障碍:

由组件化架构图可以看出,组件间相互独立,没有依赖,也就没有关系,也就无法传递信息,那么要如何交流呢?

这时就需要用到基础层base module, 因为组javaee件层的模块都依赖于基础层;

Android中ac其他货币资金包括哪些内容tivity,fragment,service间信息传递相对复杂, 如果其他应收款是什么科目用系统级别的广播, 有耗时,容易被捕捉,无法干预,可传输数据类型少等弊端,于是大佬们就搞出了事件总线;

下面是三种目前常用的事件总线框架:

1. EventBus:

一款针对Android优化的发布/订阅事java面试题件总线,主要功能是替代handler,intenideast,broadcast;优点是开销小,代码优雅,将发送者和接系统运维工程师收者解耦;

/**
* 演示eventBus的使用
*/

//1. 定义要传递的事件实体
data class TestEvent(val params: String)

class EventBusActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_eventbus)
}

//2. 准备订阅者
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(event: TestEvent) {
LjyLogUtil.d(event.params)
}

//3. 注册订阅者
override fun onStart() {
super.onStart()
EventBus.getDefault().register(this)
}

//4. 解绑订阅者
override fun onStop() {
super.onStop()
EventBus.getDefault().unregister(this)
}

fun onBtnClick(view: View) {
when (view.id) {
//5. 发送事件, 实际场景中发送事件的发送者一般在其他页面或模块中
R.id.btn_send_event -> EventBus.getDefault().post(TestEvent("测试一下事件发送"))
}
}

}

EventBus2.x的版本和3.x是有很大区别的:
1. 2.x使用的是运行时注解,采用了反射的方式对整个注册的类的所有方法进行扫描来完成注册,因而会对性能有一定影响;
2. 3.x使用的是编译时注解,Java文件会编译成.class文件,再对class文件进行打包等一系列处理。在编译成.class文件时,
EventBus会使用EventBusAnnotationProcessor注解处理器读取@Subscribe()注解并解析、处理其中的信息,
然后生成Java类来保存所有订阅者的订阅信息。这样就创建出了对文件或类的索引关系,并将其编入到apk中。
3. 从EventBus3.0开始使用了对象池缓存减少了创建对象的开销。

EventBus给Android开发者世界带来了一种新的框架和思想,就是消息的发布和订阅。这种思想在其后很多框架中都得到了应用。
2. RxBUs

RxBus不是一个库,而是一个文件,实现只有短短30行代码。RxBus本身不需要过多分析,它的强大完全来自于它基于的RxJava技术。

public class RxBus {

/**
* Instance of {@link Bus}
*/
private static Bus sBus;

/**
* Get the instance of {@link Bus}
*
* @return
*/
public static synchronized Bus get() {
if (sBus == null) {
sBus = new Bus(ThreadEnforcer.ANY);
}
return sBus;
}
}

RxBus有很多实现,如:
AndroidKnife/RxBus(https://github.com/AndroidKnife/RxBus)(即上面的代码)
Blankj/RxBus(https://github.com/Blankj/RxBus)

下面是使用rxbus的demo
//1. rxbus的实现类
package com.ljy.publicdemo.util;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;

import com.trello.lifecycle2.android.lifecycle.AndroidLifecycle;
import com.trello.rxlifecycle2.LifecycleProvider;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.subjects.PublishSubject;
import io.reactivex.subjects.Subject;

/**
* @Author: LiuJinYang
* @CreateDate: 2020/5/11 17:01
*/
public class RxBusUtil {
private volatile static RxBusUtil mDefaultInstance;
private final Subject<Object> mBus;

private final Map<Class<?>, Object> mStickyEventMap;

private RxBusUtil() {
mBus = PublishSubject.create().toSerialized();
mStickyEventMap = new ConcurrentHashMap<>();
}

public static RxBusUtil getInstance() {
if (mDefaultInstance == null) {
synchronized (RxBusUtil.class) {
if (mDefaultInstance == null) {
mDefaultInstance = new RxBusUtil();
}
}
}
return mDefaultInstance;
}

/**
* 发送事件
*/
public void post(Object event) {
mBus.onNext(event);
}

/**
* 使用Rxlifecycle解决RxJava引起的内存泄漏
*/
public <T> Observable<T> toObservable(LifecycleOwner owner, final Class<T> eventType) {
LifecycleProvider<Lifecycle.Event> provider = AndroidLifecycle.createLifecycleProvider(owner);
return mBus.ofType(eventType).compose(provider.<T>bindToLifecycle());
}

/**
* 判断是否有订阅者
*/
public boolean hasObservers() {
return mBus.hasObservers();
}

public void reset() {
mDefaultInstance = null;
}


/**
* Stciky 相关
*/

/**
* 发送一个新Sticky事件
*/
public void postSticky(Object event) {
synchronized (mStickyEventMap) {
mStickyEventMap.put(event.getClass(), event);
}
post(event);
}

/**
* 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者
* 使用Rxlifecycle解决RxJava引起的内存泄漏
*/
public <T> Observable<T> toObservableSticky(LifecycleOwner owner, final Class<T> eventType) {
synchronized (mStickyEventMap) {
LifecycleProvider<Lifecycle.Event> provider = AndroidLifecycle.createLifecycleProvider(owner);
Observable<T> observable = mBus.ofType(eventType).compose(provider.<T>bindToLifecycle());
final Object event = mStickyEventMap.get(eventType);

if (event != null) {
return observable.mergeWith(Observable.create(new ObservableOnSubscribe<T>() {
@Override
public void subscribe(ObservableEmitter<T> subscriber) throws Exception {
subscriber.onNext(eventType.cast(event));
}
}));
} else {
return observable;
}
}
}

/**
* 根据eventType获取Sticky事件
*/
public <T> T getStickyEvent(Class<T> eventType) {
synchronized (mStickyEventMap) {
return eventType.cast(mStickyEventMap.get(eventType));
}
}

/**
* 移除指定eventType的Sticky事件
*/
public <T> T removeStickyEvent(Class<T> eventType) {
synchronized (mStickyEventMap) {
return eventType.cast(mStickyEventMap.remove(eventType));
}
}

/**
* 移除所有的Sticky事件
*/
public void removeAllStickyEvents() {
synchronized (mStickyEventMap) {
mStickyEventMap.clear();
}
}
}

//2. 使用
class RxBusActivity:AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_rx_bus)
registerRxBus()
}

private fun registerRxBus() {
RxBusUtil.getInstance().toObservable(this, TestEvent::class.java).subscribe(object : Observer<TestEvent> {

override fun onSubscribe(d: Disposable) {
LjyLogUtil.d("onSubscribe:回调返回Disposable 对象,让观察者管理订阅状态, 例如取消订阅")
}

override fun onNext(event: TestEvent) {
LjyLogUtil.d("onNext:数据接收处理")
LjyLogUtil.d(event.params)
}

override fun onError(e: Throwable) {
LjyLogUtil.d("onError:发生异常,终止事件流")
}

override fun onComplete() {
LjyLogUtil.d("onComplete:事件流结束")
}
})
}

fun onBtnClick(view: View) {
when(view.id){
R.id.btn_rx_bus->RxBusUtil.getInstance().post(TestEvent("测试rxBus发送消息"))
}
}
}

//因为用了Rxlifecycle,推出activity时无需解绑

与Ev架构师和程序员的区别entBus相比的优点,其实也就是rxJava的优其他综合收益属于什么科目点:1、RxJava的Observable有onError、onComjava编译器plete等状态回调。2、RxJava使用组合而非嵌套的方式,避免了回调地狱。3、RxJava的线程调度设计的更加优秀,其他更简单易用。ideology4、RxJava可使用多种操作符来进行链式调用来实现复杂的逻辑。5、RxJava的信息效率高于EventBus2.x,低于EventBus3.x。

那么技术选型时如何取舍呢?如果项目中使用了RxJava,则使用RxBus,否则使用EventBus3.javaeex

3. LiideveDataBu架构师工资s

LiveDataBus是基于LiveData实现的类似EventBus的消息通其他综合收益信框架,它是基于LiveData实现的,完全可以代替EventBus,RxBus;

为什么会有他呢架构师和程序员的区别?Handler : 容易导致内存泄漏,空指针,高耦合,不利于维护EventBus :原理实现复杂,无法混淆,需要手动绑定生命周期RxBu系统运维工作内容s:依赖于RxJava,包太大,影响apk大小,app启动时间

//初代实现如下
ublic final class LiveDataBus {

private final Map<String, MutableLiveData<Object>> bus;

private LiveDataBus() {
bus = new HashMap<>();
}

private static class SingletonHolder {
private static final LiveDataBus DATA_BUS = new LiveDataBus();
}

public static LiveDataBus get() {
return SingletonHolder.DATA_BUS;
}

public <T> MutableLiveData<T> getChannel(String target, Class<T> type) {
if (!bus.containsKey(target)) {
bus.put(target, new MutableLiveData<>());
}
return (MutableLiveData<T>) bus.get(target);
}

public MutableLiveData<Object> getChannel(String target) {
return getChannel(target, Object.class);
}
}
//使用
注册订阅:
LiveDataBus.get().getChannel("key_test", Boolean.class)
.observe(this, new Observer<Boolean>() {
@Override
public void onChanged(@Nullable Boolean aBoolean) {
}
});
发送消息:
LiveDataBus.get().getChannel("key_test").setValue(true);

其项目地址如下:​​github.com/JeremyLiao/…​​​作者另外的项目SmartEventBus,基于LiveEventBus实现,能让你其他和其它的区别定制自己的消息ideology总线​​github.com/JeremyLiao/…​​

4. 组件化事件总线的考量

其实目前常用的各种事件其他综合收益总线xxBus原理都差不多

那么在组件化项目中如何identical使用这些事件总线呢

1.EventBus,RxBus: 将xxEvenideat消息容器和事件总线框架的依赖放到base module,其他模idea块组件依赖于base module;但是这样每个模块改动都需要增删改baseModule中的消息容器ideology, 组件化要求功能模块独立, 各组件应该尽量避免影响base module;2. LiveDataBus: 无需建立消息模型,但无法想前两者一样拥有类名索引,无法引导正确的编写代码,也无法传递自定义实体到其他模块;3. 组件化中使用EventBus,RxBus,为了更大程度的解耦,可以独立出一个事件总线module,添加事件的实体都在这个module中,base moduljava面试题e依赖 这个事件总线module对事件通信的解耦, 抽离事件到事件总线module中减少对base module的影响;

其他综合收益是今阳,如果想要进阶和了解更多的干货,欢迎idea关注公众号”今阳说“接架构是什么意思收我的最其他垃圾新文章