Android base development library to make development easier. DevRing & Demo address: github.com/LJYcoder/De…

Study/Reference address: http://blog.csdn.net/itachi85/article/details/52205464 http://blog.csdn.net/Tencent_Bugly/article/details/51354693 http://blog.csdn.net/qq_28746251/article/details/51476389

preface

EventBus is a publish/subscribe based EventBus (data communication framework) that simplifies data communication between components and threads with low coupling and overhead. In version 3.0, annotations are used to declare subscriber functions and their related properties, making the process easier, and indexes are provided to help improve performance.

If you don’t like using EventBus and want to use RxJava to encapsulate an RxBus for communication, the Demo also provides the code


introduce

The following introduces EventBus in terms of configuration, basic usage, sticky events, using Index optimization, simple encapsulation, and obfuscating.

1. The configuration

Add it in build.gradle under Module

//EventBus
compile 'org. Greenrobot: eventbus: 3.0.0'
annotationProcessor 'org. Greenrobot: eventbus -- the annotation processor: 3.0.1'// Enable Index acceleration for eventBus
Copy the code

2. Basic usage

The usage steps are divided into five steps: defining events, subscribing events, sending events, processing events, and unsubscribing events

2.1 Defining Events

Start by defining an event class that you want to send, and add the data variables you want to send. In addition to basic data types, variable types can also be custom entity classes.

public class MovieEvent {
    private int count;

    public MovieEvent(int count) {
        this.count = count;
    }

    public int getCount(a) {
        return count;
    }

    public void setCount(int count) {
        this.count = count; }}Copy the code

2.2 Subscription Events

Subscribe to events where you want to receive them:

public class MovieActivity{...@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Make sure you have not subscribed before, and then call the subscribe statement to avoid errors
        if(! EventBus.getDefault().isRegistered(subscriber)){ EventBus.getDefault().register(subscriber); }}... }Copy the code

2.3 Sending Events

Where you want to send the event, call

EventBus.getDefault().post(new MovieEvent(1));
Copy the code

It is important to note that the sent event is passed by reference, which means that after you send an event, you modify the received event in the event handler, and the event at the source will also change. Therefore, if you do not want to affect the source data, you are advised to send new objects before sending.

In addition, EventBus provides a method for sending sticky events, which are covered below.

EventBus.getDefault().postSticky(new MovieEvent(1));
Copy the code

2.4 Handling Events

Add a method that handles the event where the event is received, in the same class as the subscribed event method to ensure that the event is successfully subscribed

public class MovieActivity{...// Declare a method for handling events
    @Subscribe
    public void handlerEvent(MovieEvent event) {
    	// Handle events
        intcount = event.getCount(); . }... }Copy the code

You can define the name of the event handler, but you must Subscribe with the @subscribe annotation to declare it to be an event receive handler. The parameters to the method specify the type of event you want to receive. For example, if the parameter is MovieEvent Event, events of type MovieEvent will be received. Events of other types will not be received.

In addition, @SUBSCRIBE can set the thread in which the event is processed, the priority of the event to receive, and whether it is a sticky event

  • The thread in which the event is processed
@subscribe (threadMode = thread type)Copy the code

There are four options for thread types:

  1. Threadmode. POSTING: The default type. Indicates that the thread in which the event is processed will be the same as the thread in which the event was sent, that is, both execute on the same thread.
  2. Threadmode. MAIN: Indicates that the thread in which the event is processed will switch to the UI MAIN thread. If the thread sending the event is the main UI thread, it will not switch.
  3. Threadmode. BACKGROUND: Indicates that the thread in which the event is processed will be switched to the BACKGROUND thread. If the thread sending the event is a background thread, the switch will not happen.
  4. Threadmode. ASYNC: Indicates that the thread in which the event is processed will be switched to a newly created independent child thread.
  • priority
@Subscribe(priority = 100)
Copy the code

Priority specifies the priority for receiving events. The default value is 0. The higher-priority event handler will receive the sent event first. You can intercept the event in the higher-priority event handler to prevent it from being passed down

EventBus.getDefault().cancelEventDelivery(event);
Copy the code
  • Viscous event
@Subscribe(sticky = true)
Copy the code

Sticky Specifies whether to accept sticky events that have been sent before the subscription. The default value is false.

2.5 Unsubscribing

Unsubscribe when you exit or do not need to receive events

public class MovieActivity{...@Override
    protected void onDestroy(a) {
        super.onDestroy();
        // Unsubscribe
        if(EventBus.getDefault().isRegistered(subscriber)) { EventBus.getDefault().unregister(subscriber); }}... }Copy the code

3. Sticky events

Generally, we use the process as follows: subscribe event – send event – receive event processing. Now if you want to send events – subscribe events – receive processing events, can this be done? The answer is yes. The sticky events provided by EventBus enable this scenario.

3.1 Procedure

The usage procedure is the same as that of ordinary events, but postSticky(event) is invoked for event sending, and @subscriber (sticky = true) must be declared for event processing function.

// Event sender

// Send sticky events
EventBus.getDefault().postSticky(new MovieEvent(1));
Copy the code
// Event receiver handler

// Subscribe to events after sending sticky events
EventBus.getDefault().register(this);// Register the event to receive

// Receive sticky events emitted before processing the subscription
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void handleEvent(MovieEvent event) {
	// Handle events
    int count = event.getCount();
}
Copy the code

3.2 Application Scenarios

Here is an example of a usage scenario: jumping between activities. Reference from http://www.cnblogs.com/ldq2016/p/5387444.html we are regularly use Intent carrying data, if you want to pass the custom entity class, you also need to be serialized operation. Here’s an overview of how to implement this scenario using EventBus’s sticky events.

ActivityA jumps to ActivityB and passes the Movie object.

// Code in ActivityA

Movie movie = new Movie();
// Send sticky events, send movie
EventBus.getDefault().postSticky(movie);
// Jump to ActivityB
startActivity(new Intent(this, ActivityB.class));
Copy the code
// Code in ActivityB

// Subscribe to events
EventBus.getDefault().register(this);

// Get the sticky events sent by ActivityA before subscribing
@Subscribe(sticky = true)
public void getDataFromOtherActivity(Movie movie) {
	// Get ActivityA's Movie object.
}
Copy the code

If you have other usage scenarios, please share them in the comments

3.3 supplement

1) EventBus only stores the latest sent sticky events. 2) Manually obtain and remove sticky events

// Manually get stickiness events
MovieEvent movieEvent = EventBus.getDefault().getStickyEvent(MovieEvent.class);

if(movieEvent ! =null) {
    // Remove sticky events
    EventBus.getDefault().removeStickyEvent(movieEvent);
}
Copy the code

3) After sending sticky events, all subscribers who subscribed to events before sending them will receive sticky events of the same type, regardless of whether their event handling method is declared as sticky=true. However, for subscribers who subscribe events after sending, their event processing method must be declared as sticky=true in order to receive sticky events of the same type.

4. Optimize with index

Prior to 3.0, EventBus used reflection rather than annotations when iterating through callbacks to find subscribers to ensure performance. In 3.0, due to annotations, performance was significantly lower than in 2.4, as you can see in the figure below. To ensure high performance with annotations, EventBus provides a way to improve performance by turning Index on, and as you can see in the figure below, the performance increases many times when Index is turned on.

Here’s how to build and enable indexes.

4.1 Generating An Index

Many articles about Index on the web are generated by adding the following configuration

// Build. Gradle file under project

buildscript {
    dependencies {
        classpath 'com. Neenbedankt. Gradle. Plugins: android - apt: 1.8'}}// Build. Gradle file in module

apply plugin: 'com.neenbedankt.android-apt'
apt {
    arguments {
        eventBusIndex "com.dev.base.MyEventBusIndex"
    }
}
dependencies {
    compile 'org. Greenrobot: eventbus: 3.0.0'
    apt 'org. Greenrobot: eventbus -- the annotation processor: 3.0.1'
}
Copy the code

However, if your project also uses the ButterKnife library, adding the above configuration will cause ButterKnife to not work properly; In addition, the author of Android-apt has announced on the official website that it will not continue to maintain Android-apt in the future, so it is not recommended to implement this method, but to use the official plug-in annotationProcessor released by Android to replace APT. It’s easier to configure the annotationProcessor to generate index, as follows:

// Build. Gradle file in module

android{
    defaultConfig {
            / /... Omit other configurations

            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [ eventBusIndex : "com.dev.base.MyEventBusIndex" ]
               }
            }
    }
}


dependencies {
    compile 'org. Greenrobot: eventbus: 3.0.0'
    annotationProcessor 'org. Greenrobot: eventbus -- the annotation processor: 3.0.1'
}

Copy the code

After adding the above configuration and compiling and running the project, if the specified Index class is generated under \build\generated\source\apt\debug\ project package name \, it means that the Index is generated successfully, as shown in the following figure.

4.2 Enabling Indexes

After the index is generated, turn it on by calling the addIndex() method in Appliction.

EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
Copy the code

5. Simple encapsulation

public class EventBusManager {

    // Enable Index acceleration
    public static void openIndex(a) {
        EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
    }

    // Subscribe to events
    public static void register(Object subscriber) {
        if(!EventBus.getDefault().isRegistered(subscriber)){
            EventBus.getDefault().register(subscriber);
        }
    }

    // Unsubscribe
    public static void unregister(Object subscriber) {
        if(EventBus.getDefault().isRegistered(subscriber)) { EventBus.getDefault().unregister(subscriber); }}// Terminate the event to continue
    public static void cancelDelivery(Object event) {
        EventBus.getDefault().cancelEventDelivery(event);
    }

    // Get the sticky events saved
    public static <T> T getStickyEvent(Class<T> classType){
        return EventBus.getDefault().getStickyEvent(classType);
    }

    // Remove sticky events from the save
    public static void removeStickyEvent(Object event) {
        EventBus.getDefault().removeStickyEvent(event);
    }

    // Send events
    public static void postEvent(Object event){
        EventBus.getDefault().post(event);
    }

    // Send sticky events
    public static void postStickyEvent(Object event) { EventBus.getDefault().postSticky(event); }}Copy the code

DevRing/Demo encapsulates EventBus. In activities and Fragments, simply override isUseEventBus() and return true, and the page will be automatically subscribed and unsubscribed. See the code for details.

6. Confused

Add the following to the proGuard-rules. pro file for obfuscation configuration

#EventBus start - KeepAttributes *Annotation* # You must add this - keepclassmembers class * * {@ org. Greenrobot. Eventbus. Subscribe < the methods >; } -keep enum org.greenrobot.eventbus.ThreadMode { *; } # if you use the Async type thread - keepclassmembers class * extends org. Greenrobot. Eventbus. Util. ThrowableFailureEvent { <init>(java.lang.Throwable); } # EventBus endCopy the code