Like attention, no more lost, your support means a lot to me!

🔥 Hi, I’m Chouchou. GitHub · Android-Notebook has been included in this article. Welcome to grow up with Chouchou Peng. (Contact information at GitHub)

preface

  • The EventBus mechanism is very common in Android development.
  • Today, I’ll put together a detailed tutorial on how to use EventBus, aiming for simplicity and depth. Please be sure to like and follow if you can help, it really means a lot to me.

directory


Front knowledge

The content of this article will involve the following pre/related knowledge, dear I have prepared for you, please enjoy ~

  • APT: 【 Like 】
  • Comments: “Java | annotations (including Kotlin)”
  • Confused: What did the Android | code confusion?”

1. The EventBus overview

  • Definition: a setAndroid / JavaAn event subscription/publishing framework, open-source by the GreenRobot team.

  • Purpose: To pass data or events to the corresponding subscriber in a component/thread communication scenario.

  • Why use itEventBus(Characteristic)?

For application scenarios of Android component/thread communication, EventBus is more concise and reliable than traditional interface monitoring, Handler, Executors, and LocalBroadcastManager. Details are as follows:

  • 1. Use the event bus framework to achieve loose coupling between event publishers and subscribers;
  • 2. Provides transparent interthread communication, hiding thread switching between publishing thread and subscribing thread.

  • Concepts related to EventBus

The concepts related to the EventBus mechanism are as follows:


2. Procedure

Before analyzing how to use EventBus, let’s describe how to use EventBus.

2.1 Step 1: Add a dependency

  • In the module levelbuild.gradleAdd a dependency to:
Dependencies {def eventbus_version = '3.2.0' implementation "greenrobot: $eventbus_version"}Copy the code
  • When using compile-time indexes, you also need dependenciesAnnotation processing toolNote that pure Java projects and Kotlin use different annotation processing tools:
    • Java project usageannotationProcessor
    • Kotlin project usekapt
/ / Java: android {defaultConfig {javaCompileOptions {annotationProcessorOptions {the arguments = [eventBusIndex: '. Com. Have al-qeada ood. MyEventBusAppIndex]}}}} dependencies {def eventbus_version = '3.2.0' implementation "org.greenrobot:eventbus:$eventbus_version" annotationProcessor "org.greenrobot:eventbus-annotation-processor:$eventbus_version" }Copy the code
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied
 
dependencies {
    def eventbus_version = '3.2.0'
    implementation "org.greenrobot:eventbus:$eventbus_version"
    kapt "org.greenrobot:eventbus-annotation-processor:$eventbus_version"
}
 
kapt {
    arguments {
        arg('eventBusIndex', 'com.have.a.good.MyEventBusAppIndex')
    }
}
Copy the code

2.2 Step 2: Prepare subscribers

The subscriber needs to implement the Subscribe method, decorated with the @subscribe annotation, as follows:

For example:

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
Copy the code

In the @SUBSCRIBE annotation, the threadMode parameter determines the thread model to use. There are currently five:

2.3 Step 3: Register and unregister

Subscribers need to be registered before an event can be published. At the end of the subscriber life cycle, the subscriber needs to be unregistered.

For example:

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}
 
@Override
public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
}
Copy the code

2.4 Step 4: Publish events

After registering subscribers, events can be published, and there are currently two types of events:

  • callEventBus#post(Object)Post common events
  • callEventBus#postSticky(Object)Publishing sticky Events

For example:

EventBus.getDefault().post(new MessageEvent("Hello everyone!" ));Copy the code

The characteristics of viscous events are as follows:

For example:

1, @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) public void onEvent(MessageEvent event) { textField.setText(event.message); } eventbus.getDefault ().poststicky (new MessageEvent("Hello everyone! )); MessageEvent stickyEvent = eventBus.getDefault ().getStickyevent (MessageEvent.class); if(stickyEvent ! Eventbus.getdefault ().removestickyevent (stickyEvent); Eventbus.getdefault ().removesticKyevent (messageEvent.class); if(stickyEvent ! = null) { // do something. }Copy the code

3. Compile-time indexes

One of the biggest improvements to EventBus 3.x over EventBus 2.x is the compile-time index.

To generate compile-time indexes, you first need to configure the index file in build.gradle, for example:

kapt {
    arguments {
        arg('eventBusIndex', 'com.have.a.good.MyEventBusAppIndex')
    }
}
Copy the code

At compile time, the annotation processor parses the @SUBSCRIBE annotated method to generate the index class myeventBusAppIndex.java. What you need to do is add indexes at runtime build time, for example:

EventBus eventBus = EventBus.builder()
    .addIndex(new MyEventBusAppIndex())
    .build();
Copy the code

Note that the index class configuration only applies to the current Module, so you need to add the index class configuration to each module-level build.gradle that contains subscribers, for example:

// App module apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied kapt { arguments { arg('eventBusIndex', 'com.have.a.good.MyEventBusAppIndex') } } dependencies { ... Kapt "org. Greenrobot: eventbus -- the annotation processor: 3.2.0" implementation project (path: ':base') } // Lib module apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied kapt { arguments { arg('eventBusIndex', 'com.have.a.good.MyEventBusLibIndex') } } dependencies { ... API 'org. Greenrobot: eventbus: 3.2.0' kapt "org. Greenrobot: eventbus -- the annotation processor: 3.2.0" implementation project(path: ':base') }Copy the code

The above configuration generates two index class files, myeventBusAppIndex. Java contains only the index of the subscriber in the App Module, and myeventbuslibindex. Java contains only the index of the subscriber in the Lib Module.


4. The Builder pattern

The Builder Pattern is standard for open source libraries, and EventBus is no exception. You can use EventBusBuilder to build an EventBus instance, or you can call eventbus.getDefault () to get the default EventBus instance.

  • 1. Configure exception handling
Configuration items describe The default value
logSubscriberExceptions If the subscription function executes abnormally, the exception information is printed true
sendSubscriberExceptionEvent Publish the SubscriberExceptionEvent event when there is an exception in the execution of the subscription function true
throwSubscriberException When the subscription function executes abnormally, a SubscriberException is thrown false
logNoSubscriberMessages If the event does not match the subscription function, information is printed true
sendNoSubscriberEvent The NoSubscriberEvent is published when no subscription function matches the event true
  • 2. Index configuration
Configuration items describe The default value
ignoreGeneratedIndex Ignore the subscriber index false
addIndex(SubscriberInfoIndex index) Add a subscriber index There is no
  • 3. Event subscription configuration
Configuration items describe The default value
eventInheritance Whether to trigger the superclass event subscription function true
executorService(ExecutorService executorService) The thread pool Executors#

newCachedThreadPool()
strictMethodVerification Whether the subscription function signature is strictly validated true
skipMethodVerificationFor(Class<? > clazz) Skip method signature validation There is no

5. Confused

Both ProGuard and its successor, R8, offer compression, optimization, obfuscation, and prevalidation. Compression and optimization remove unused classes/methods/fields, and obfuscation renames classes/methods/fields with meaningless short names.

The @subscribe method is called by reflection, not directly at compile time, and the method name could not be found at run time if the anti-obfuscation rule was not added. Therefore, EventBus needs to configure the following obfuscation rules:

- Annotation keepattributes * * / / keep living all the Subscribe method of annotations - keepclassmembers class * {@ org. Greenrobot. Eventbus. Subscribe <methods>; } -keep enum org.greenrobot.eventbus.ThreadMode { *; }Copy the code

If AsyncExecutor is used, you also need to configure obfuscation rules:

-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}
Copy the code

More content: the Android | code confuse what do?”


6. Summary

  • EventBus is an Android/Java event subscription/publishing framework for delivering data or events to subscribers in component/thread communication scenarios. EventBus features decoupling of event subscribers and publishers and transparent thread switching.

  • In EventBus 3.x, subscribers need to decorate the subscription method with the @subscribe annotation. Five thread modes are available (POSTING, MAIN, MAIN_ORDERED, BACKGROUND, and ASYNC).

  • The principle behind compile-time indexing is that the compile-time annotation processor generates index tables that record event-subscription mappings and loads index tables directly at run time. If compile-time indexes are not used, it is necessary to recursively look for @SUBSCRIBE methods in the class itself and its parent class when registering subscribers, affecting performance.

  • The @subscribe method is called by reflection, not directly at compile time, and the method name could not be found at run time if the anti-obfuscation rule was not added.


Creation is not easy, your “three lian” is chouchou’s biggest motivation, we will see you next time!