Event bus
- Componentized hierarchy disorder:
As can be seen from the componentized architecture diagram, components are independent of each other. There is no dependency, so there is no relationship, and therefore no information can be transmitted. So how to communicate?
In this case, you need to use the base module, because the module of the component layer depends on the base layer;
- Event bus
Android activity, in fragments, service information transfer between relatively complex, if use broadcast system level, there are time consuming, easy to capture, unable to intervene, can transmit data types, such as less so bosses will get out of the event bus;
Here are three event bus frameworks in common use today:
1. EventBus:
A publish/subscribe event bus optimized for Android, the main function is to replace handler,intent,broadcast; Advantages are small overhead, elegant code, sender and receiver decoupled;
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: override fun onStop() {super.onstop () eventbus.getDefault (). View) { when (view.id) { //5. Send events, Eventbus.getdefault ().post(TestEvent(" TestEvent sending "))}}} The version of EventBus2.x is quite different from 3.x: 1.2. x uses runtime annotations and reflects all methods of the registered class to complete the registration, thus affecting performance. 2.3. x uses compile-time annotations, and Java files are compiled into.class files, which are packaged, and so on. Writing translated into. The class file, the EventBus will use EventBusAnnotationProcessor annotation processor reads @ the Subscribe () annotations and parsing, processing the information, then generate Java classes to hold all the subscriber's subscription information. This creates an index relationship to a file or class and compiles it into apK. 3. Object pool caching has been used since EventBus3.0 to reduce the overhead of creating objects. EventBus brings a new framework and idea to the Android developer world: publishing and subscribing messages. This idea has been applied in many subsequent frameworks.Copy the code
2. RxBUs
RxBus is not a library, but a file, implemented in just 30 lines of code. RxBus itself does not require much analysis; its power comes entirely from the RxJava technology on which it is based.
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 has many implementations, such as: AndroidKnife/RxBus (https://github.com/AndroidKnife/RxBus) (i.e., the above code) Blankj/RxBus (https://github.com/Blankj/RxBus) Rxbus package com.ljy.publicDemo.util; 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); } /** * 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()); } /** * Specifies whether there are any subscribers. */ public Boolean observers () {return mbus.hasobservers (); } public void reset() { mDefaultInstance = null; Public void postSticky(Object event) {synchronized (mStickyEventMap) {synchronized (mStickyEventMap) { mStickyEventMap.put(event.getClass(), event); } post(event); } public <T> Observable<T> Returns an observer of a particular eventType based on the eventType passed 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; Public <T> T getStickyEvent(Class<T> eventType) {synchronized (mStickyEventMap) {public <T> T getStickyEvent(Class<T> eventType) { return eventType.cast(mStickyEventMap.get(eventType)); }} public <T> T removeStickyEvent(Class<T> eventType) {synchronized (mStickyEventMap) { return eventType.cast(mStickyEventMap.remove(eventType)); } /** * removeAllStickyEvents */ public void removeAllStickyEvents() {synchronized (mStickyEventMap) { mStickyEventMap.clear(); }}} / / 2. Use the 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: callback returns Disposable to let the observer manage the subscription status, such as unsubscribe ")} Override fun onNext(event: TestEvent) {ljylogutil. d("onNext: Data receiving ") ljylogutil. d(event.params)} Override fun onError(e: Throwable) {ljylogutil. d("onError: an exception occurred, Override fun onComplete() {ljylogutil. d("onComplete: End of event ")}})} Fun onBtnClick(view: View) {when(view.id){r.i.btn_rx_bus -> rxbusutil.getInstance ().post(TestEvent(" rxBus sends messages "))}}} There is no need to unbind the activity when it is launchedCopy the code
The advantages of rxJava compared with EventBus are: 1. RxJava Observable has onError, onComplete and other state callbacks. 2. RxJava avoids callback hell by using composition rather than nesting. 3, RxJava thread scheduling design is more excellent, more simple to use. 4. RxJava can use a variety of operators to make chain calls to achieve complex logic. 5. The information efficiency of RxJava is higher than eventBus2. x and lower than EventBus3.x.
So how to choose the technology selection? If RxJava is used in the project, use RxBus, otherwise use EventBus3.x
3. LiveDataBus
LiveDataBus is a message communication framework similar to EventBus based on LiveData. It is implemented based on LiveData and can completely replace EventBus and RxBus.
Why is he there? EventBus: The implementation is complex and cannot be confused, which requires manual binding of the life cycle. RxBus: Depends on RxJava. The package size is too large, which affects the APK size and app startup time
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); }} // Use register subscription: LiveDataBus.get().getChannel("key_test", Boolean.class) .observe(this, new Observer<Boolean>() { @Override public void onChanged(@Nullable Boolean aBoolean) { } }); To send a message: liveDatabus.get ().getChannel("key_test").setValue(true);Copy the code
The project address is: github.com/JeremyLiao/… The author’s other project, SmartEventBus, is based on LiveEventBus implementation, which allows you to customize your own message bus github.com/JeremyLiao/…
4. Consideration of the componentized event bus
In fact, all kinds of commonly used event bus xxBus principle is similar
So how do you use these event buses in a componentized project
1.EventBus,RxBus: place xxEvent message container and EventBus framework dependencies on the base module, and other module components depend on the base module; However, each module change needs to add, delete, or change the message container in baseModule. Componentization requires independent function modules. Components should avoid affecting the Base Module. 2. LiveDataBus: No need to build a message model, but can’t have class name indexes like the first two, can’t lead to proper writing code, and can’t pass custom entities to other modules; 3. Use EventBus and RxBus in componentization. In order to achieve a greater degree of decoupling, an EventBus module can be created independently. The Base Module relies on the decoupling of the event bus module to the event communication, and extracts events from the event bus module to reduce the impact on the Base Module.