EventBus main roles:
· Event object passed by Event
· Subscriber to the Subscriber event
The publisher of the Publisher event
ThreadMode defines in which thread the function executes
1. Steps to use EventBus :
1. Define the event
public class MessageEvent{ publicfinal String message; public MessageEvent(String message) { this.message = message; } }
2. Prepare subscribers
The implementation of subscription is sent by calling the Subscriber method before sending the message EventBus3.0, but after 3.0 it is implemented by the @Subscribe annotation
// This method will be called when a MessageEvent is posted (in the UI thread for Toast) @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEventevent) { Toast.makeText(getActivity(),event.message, Toast.LENGTH_SHORT).show(); } // This method will be called when a SomeOtherEvent is posted @Subscribe public void handleSomethingElse(SomeOtherEventevent) { doSomethingWith(event); }
It needs to be registered and deregistered according to the onStart/onStop method of the life cycle of Activities and Fragments. Subscribers also need to register and deregister on the bus. Only when the user registers, they can receive events.
@Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public voidonStop() { EventBus.getDefault().unregister(this); super.onStop(); }
3. Send events
Events can be sent anywhere, and all matching event types can receive it
EventBus.getDefault().post(newMessageEvent("Hello everyone!"));
Two, EventBus four sending modes
ThreadMode: POSTING and the publisher are in the same thread
By default, Subscribe and Post will be performed in the same Thread, and the delivery of Events is synchronous. Once the publication is completed, all Subscribers will be called. In this mode, you can Completely avoid thread (Thread) conversion, it occupies the least memory overhead, because it executes outside the main thread for a very short time, it is recommended to use this mode when completing some simple tasks. This mode may be executed in the main thread, and the event should be released quickly after the event is processed to avoid blocking the thread.
// Called in the same thread (default) // ThreadMode is optional here @Subscribe(threadMode = ThreadMode.POSTING) public voidonMessage(MessageEventevent) { log(event.message); }
ThreadMode: MAIN in theAndroidmain thread
Subscribers (Subscribers) will be called in the main thread of Android. If the sending (POST) is also in the main thread, the event processing will be executed immediately (similar to the description in ThreadMode.POSTING mode), and the same event processing is completed. should return immediately so as not to block the thread
// Called in Android UI's main thread @Subscribe(threadMode = ThreadMode.MAIN) public void onMessage(MessageEvent event) { textField.setText(event.message); }
ThreadMode: BACKGROUD background thread
The subscriber will be called in a background thread, and if the sending thread is the main thread, the processing of the event will be executed immediately. In the main thread, EventBus uses a single background thread and events will be delivered sequentially. The same event should be returned immediately after processing, so as not to block the thread
// Called in the background thread @Subscribe(threadMode = ThreadMode.BACKGROUND) public void onMessage(MessageEventevent){ saveToDisk(event.message); }
ThreadMode: ASYNC asynchronous thread
The handling of the event will be called in a separate thread. Independent of the sending thread and the main thread. With this mode, publishing events will not wait for their processing, and this mode can perform time-consuming operations such as: accessing the network. By limiting the number of threads, a large number of long-term asynchronous processing, to prevent multi-threaded concurrency.
EventBus reuses completed asynchronous processing using a thread pool to manage events.
// Called in a separate thread @Subscribe(threadMode = ThreadMode.ASYNC) public voidonMessage(MessageEventevent){ backend.send(event.message); }
3. EventBus configuration
EventBus is managed using the EventBusBuilder class, e.g. keeping subscriptions and sending via the builder
EventBus eventBus = EventBus.builder() .logNoSubscriberMessages(false) .sendNoSubscriberEvent(false) .build();An example where a subscriber needs to throw an exception
EventBuseventBus=EventBus.builder().throwSubscriberException(true).build();
Note: By default, subscribers can catch a SubscriberExceptionEvent without handling
The link below is the API of EventBusBuilder
http://greenrobot.org/files/eventbus/javadoc/3.0/org/greenrobot/eventbus/EventBusBuilder.html
Configure the default EventBus instance
Use EventBus.getDefault to easily get an instance of EventBus
EventBusBuilder can also get the default instance by calling installDefaultEventBus
EventBus can be configured to throw exceptions, such as throwing exceptions under DEBUG
EventBus .builder() .throwSubscriberException(BuildConfig.DEBUG) .installDefaultEventBus();
Note: The above operation can only be used before the default instance of EventBus is used for the first time, and then installDefaultEventBus () can be called to throw an exception. This design is to ensure the consistency of the APP.
四、Sticky Events
Explanation: What is a Sticky event? Sticky means sticky. In Android development, the Sticky event only refers to a special type of event consumers who register the event after the event is published and can also receive the event. Such as StickyBroadcast, that is, sticky broadcast. Under normal circumstances, if the sender sends a broadcast, and the receiver registers its own receiver after the broadcast is sent, this means that the receiver cannot receive the broadcast just now, so Android introduces StickyBroadcast, which will be saved after the broadcast is sent. The broadcast (Intent) that has just been sent is sent to the amount, so that when the receiver registers the Receiver, it can receive the broadcast that has just been published. This allows us to pre-process some events and deliver these events to consumers when there are consumers.
AndroidEventbus also provides such a function. The difference is that AndroidEvenBus will store all Sticky events. If an event does not need to be stored, it needs to be removed manually. Users publish events in the form of Sticky, and consumers also need to register in the form of Sticky. Of course, this registration is the same as the regular registration function except that it can receive Sticky events, and other types of events will also be processed normally.
Official description:
Some events carry information that is ofinterest after the event is posted. For example, an event signals that someinitialization is complete. Or if you have some sensor or location data and youwant to hold on the most recent values. Instead of implementing your owncaching, you can use sticky events. So EventBus keeps the last sticky event ofa certain type in memory. Then the sticky event can be delivered to subscribersor queried explicitly. Thus, you don’t need any special logic to consideralready available data.
Translation: Some events will bring messages after the event is published, for example, an event already exists when it is initialized. Or maybe you already have some sensor and location data, but want to get the latest values. Instead of implementing the cache yourself, you can use StickyEvent instead. So EventBus keeps the last sticky event of a specific type in memory. Sticky events can then be sent to subscribers, or queries can be displayed. Therefore, no needDo this by doing special logic to the data we already have.
Sticky Example
Let's say a sticky event was posted some time ago.
EventBus .getDefault() .postSticky(newMessageEvent("Hello everyone!"));
Now start an Activity. During this time so sticky users will immediately get the sticky events sent first
@Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } // UI updates must run on MainThread @Subscribe(sticky=true,threadMode= ThreadMode.MAIN) public voidonEvent(MessageEventevent){ textField.setText(event.message); } @Override public void onStop() { EventBus.getDefault().unregister(this); super.onStop(); }
Manually remove SickyEvent
As you can see, the last sticky event will automatically match the subscriber when the subscriber registers. But sometimes we need to manually check for sticky events. Sometimes in order to avoid re-delivery of sticky events we usually need to remove (consume) this event.
MessageEventstickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class); // Better check that an event wasactually posted before if(stickyEvent!=null) { // "Consume"the sticky event EventBus.getDefault().removeStickyEvent(stickyEvent); // Now dosomething with it }
This removeStickyEvent is an overloaded method. When you use this class, the return value is the previous sticky event. Using this change we can change the previous example
Although we mostly use EventBus without priority and event cancellation, we still use it in some special cases. For example, when our app is in the foreground, it may trigger some UI logic, but when it is not visible, there will be different situations. Cancellation of priorities and events
MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class); // Better check that an event was actually posted before if(stickyEvent!=null) { // Now do something with it }
User priority
In order to change the delivery order of events, it is necessary to give events a priority to achieve the purpose.
Note: Priority does not affect the execution order of different thread modes (ie in ThreadMode). within the thread where the event is to be delivered (That is, in ThreadMode) high priority is executed before low priority. The default priority is 0.
@Subscribe(priority = 1); public void onEvent(MessageEvent event) { ... }
Cancel the delivery of an event
We can cancel user event processing through the function cancelEventDelivery(Object event). All subscribed events will be cancelled and subsequent subscriptions will not receive the event.
// Calledin the same thread (default) @Subscribe public void onEvent(MessageEventevent){ // Process the event ... //Prevent delivery to other subscribers EventBus.getDefault().cancelEventDelivery(event) ; }
Events are usually canceled by high-priority subscribers. Cancellation is limited to events that are running in the published thread (ThreadMode.PostThread).
Fives,
Subscriber index is a new feature of EventBus 3.0. This is an optional optimizer that can bring subscribers higher speeds.
The EventBus annotator creates the subscriber index at compile time. Although the EventBus does not have to use the index, it is recommended to use the Index for better performance.
Conditions of use of the index
Note: Indexes can only be used in @Subscriber methods, and when the class where the subscriber and Event are located is required to be public modified, and the @Subscriber annotation cannot be used in anonymous inner classes. When we do not use the EventBus index for event processing, it can also run normally, but because the reflection mechanism is used at runtime, the performance will be slightly lower.
How to generate indexes? Use of AnnotationProcessor
The Gradle plugin is required to be version 2.2.0 or later, and the annotationProcessor must be configured in build.gradle. You also need to use eventBusIndex to assign it to the class where you want to generate Index
android { defaultConfig{ javaCompileOptions{ annotationProcessorOptions{ arguments = [ eventBusIndex:'com.example.myapp.MyEventBusIndex' ] } } } } dependencies { compile 'org.greenrobot:eventbus:3.0.0' annotationProcessor'org.greenrobot:eventbus-annotation-processor:3.0.1' }
use kapt
EnevtBus has also opened support for Kotlin. If you want to use Kotlin, you need to configure kapt in the annotationProcessor.
apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied dependencies { compile 'org.greenrobot:eventbus:3.0.0' kapt'org.greenrobot:eventbus-annotation-processor:3.0.1' } capt { arguments { arg('eventBusIndex','com.example.myapp.MyEventBusIndex') } }
In Android, the use of apt in Android-apt plugin should be configured in EventBusAnnotationProcessorAndroid
buildscript { dependencies{ classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } apply plugin: 'com.neenbedankt.android-apt' dependencies { compile 'org.greenrobot:eventbus:3.0.0' apt 'org.greenrobot:eventbus-annotation-processor:3.0.1' } apt { arguments { eventBusIndex"com.example.myapp.MyEventBusIndex" } }
Use of indexes
After configuring the above operations, build the project, and then the business bean of EventBusIndex will be automatically generated. After generation, we can operate the index.
EventBus eventBus=EventBus.builder().addIndex(newMyEventBusIndex()).build();
You can also use the default instance of EventBus to operate
EventBus.builder().addIndex(newMyEventBusIndex()).installDefaultEventBus(); // Now the default instance uses the givenindex. Use it like this: EventBus eventBus =EventBus.getDefault();
When we use it, there will be multiple scenes that need to use Index, and these scenes will be saved in our library. Use the following methods to meet our requirements
EventBus eventBus = EventBus.builder() .addIndex(new MyEventBusAppIndex()) .addIndex(new MyEventBusLibIndex()).build();
6. EventBus confusion
Since code obfuscation will change the method name and class name, EventBus cannot be used.
-keepattributes *Annotation* -keepclassmembers class ** { @org.greenrobot.eventbus.Subscribe <methods>; } -keep enum org.greenrobot.eventbus.ThreadMode { *; } # Only required if you use AsyncExecutor -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { <init>(java.lang.Throwable); }
7. Asynchronous execution Note: Whether you use Index or not, you need to do the above operations during confusion
Asynchronous execution is like a thread pool with failure handling. AsyncExecutor wraps the exception into an event and publishes it automatically.
Disclaimer: AsyncExecutor will handle some exceptions in the background thread, but he is not the main class of EventBus.
We need AsyncExecutor when using it. Create() to create its instance and save it. Then implement the RunnableEx interface and pass it to the execution method of AsyncExecutor. When the Runnable is differentRunnableEx may throw an exception. If RunnableEx throws an exception, it will be encapsulated in ThrowableFailureEvent for publication.
An example is as follows:
AsyncExecutor.create().execute( new AsyncExecutor.RunnableEx() { @Override publicvoid run() throwsLoginException{ // No need to catch any Exception (here:LoginException) remote.login(); EventBus.getDefault().postSticky(new LoggedInEvent()); } } );
Receive part:
@Subscribe(threadMode=ThreadMode.MAIN) public void handleLoginEvent(LoggedInEventevent) { // dosomething } @Subscribe(threadMode=ThreadMode.MAIN) public void handleFailureEvent(ThrowableFailureEventevent) { // dosomething }
八、AsyncExecutor Builder
Calling the static method AsyncExecutor.builder can customize the instance of AsyncExecutor
The original text is as follows:
If youwant to customize your AsyncExecutor instance, call the static method AsyncExecutor.builder(). It willreturn a builder which lets you customize the EventBusinstance, the thread pool, and the class of the failure event.
Anothercustomization option is the execution scope, which givesfailure events context information. Forexample, a failure event may be relevant only to a specific Activity instanceor class.
If yourcustom failure event class implements the HasExecutionScope interface,AsyncExecutor will set the execution scope automatically. Like this, yoursubscriber can query the failure event for its execution scope and reactdepending on it.
Postscript: This is the first time to write a blog! If the writing is not good, you can criticize people or not. Our slogan is to try not to do anything, and I hope you can give me more opinions . Finally, let me make up my mind that this is for my own learning, not for being famous .
The last official website of the plane ticket ha!!!
http://greenrobot.org/eventbus/documentation/how-to-get-started/