Evolution of Android message bus: Replace RxBus with LiveDataBus, EventBus Android componentized scheme and Modular message bus Modular Event
Modular communication message bus design problems and implementation ideas have been clearly explained in meituanarticle. Modular Event has no open source code. This example is the implementation of alignment scheme, which needs to be mentioned in the original
Advantages and disadvantages of message bus
In general, the greatest advantage of a message bus is decoupling, so it is well suited to componentization scenarios that require complete decoupling between components. However, the main reason why message buses are criticized by many people is that message buses can be easily abused. The message bus is prone to abuse in several scenarios:
- Messages are hard to trace
Sometimes in the process of reading code, we find a place to subscribe to a message and want to see who sent the message, so we can only “trace back” by looking up the message. As a result, the process of reading the code and sorting out the logic is not coherent, and there is a sense of fragmentation.
- Messages are sent randomly without any constraint
Message buses generally have no constraints on sending messages. Neither EventBus, RxBus, nor LiveDataBus checks the message when it is sent, nor does it constrain the send call. This irregularity can even have disastrous consequences at a given moment. For example, if a subscriber subscribed to a message called login_SUCCESS, the sending message was written by a casual programmer. Instead of defining the message as a global variable, a temporary String variable was defined to send the message. Unfortunately, he spelled the message name login_success instead of login_seccess. In this case, the subscriber will never receive a successful login message, and the error will be difficult to detect.
Design goals for the componentized message bus
- Messages are defined by the component itself
When we used the message bus, we liked to define all messages in a common Java file. Componentization, however, would modify the Java file whenever a component’s message changes. So we want the component itself to define and maintain the message definition file.
- Messages with the same name that distinguish different component definitions
If messages are defined and maintained by components, it is possible that different components define messages with the same name, and the message bus framework needs to be able to distinguish such messages.
- Address the message bus shortcomings mentioned earlier
Solve the problem of message bus message tracing and message sending without constraint.
Message bus constraints
We expect the message bus framework to have the following constraints:
- You can only subscribe to and send messages that are predefined in the component. In other words, consumers cannot send and subscribe to temporary messages.
- The type of message needs to be specified at definition time.
- You need to specify which component belongs to when defining a message.
How are these constraints implemented
- Use annotations on the message definition file to define the type of message and the Module to which the message belongs.
- Define annotation handlers that collect information about messages at compile time.
- The interface is used to constrain message sending and subscription when the compiler generates a call based on the message’s information.
- The runtime builds a LiveData storage structure based on a two-level HashMap.
- The runtime uses interface+ dynamic proxy to implement real message subscription and delivery.
The structure of Meituan message bus modular- Event
- Modular -event-base: defines Anotation and other basic types
- Modular -event-core: modular-event core implementation
- Modulan-event-compiler: Annotation processor
- Modular – event – the plugin: Gradle plugin
The modular event-plugin is mainly used to scan the custom tasks of all modules. There are many examples of this implementation on the web, so I won’t explain it here. There are still three other modules in the example. There are also examples of using Module communication.
The whole process
The structure of ceventbus
- Base: defines Anotation and other basic types
- Core: Event core implementation
- Compiler: Annotation processor
use
The constant content of @eventType annotation can be translated directly into the interface method name. Because the content can be repeated, there is no guarantee that the method name will not be repeated, so you need to pay attention to it by yourself, or you can change to use constants to avoid it
@ModuleEvents(module = "common_second") public class SecondEvents { @EventType(SecondTestBean.class) public static final String TEST = "test"; @eventType () public static final String TEST2 = "TEST2 "; }Copy the code
The generated interface classes are as follows
Specific use:
SecondTestBean bean=new SecondTestBean();
bean.v="ad";
bean.id=2;
CEventBus.of(EventsDefineOfSecondEvents.class).test().setValue(bean);
Copy the code
Source address github.com/chaoyueLin/…