EventBus
is an special Publish & Subscribe Pattern implementation. EventBus
enable message to be delivered between components without requiring the components to register itself to others.
Comparing EventBus
to other Pub & Sub
implementations, EventBus
is:
- Designed to replace the original event distribution system, which requires the components register itself to each other.
- Not designed for general use,
EventBus
adds additional complexity and runtime overhead to the system. So it is not designed to replace normal method calls. - Not designed for inter-process communication as some other Pub&Sub.
EventBus
saves Android developers’ life
When developing Android application, I strongly recommend developer to introduce an EventBus
library. EventBus from GreenRobot
, Otto from Squqre
are good solutions. Or even to choose the original EventBus
in Guava library from Google.
With EventBus
, components can communicate with each other without need to hold direct reference of each other. This is very important to avoid app crashes when calling a method on a detached or destroyed component. Usually this kind of issue isn’t that easy to handle due to Android’s over-complicated life cycle management. So even in the worst case that one component is sending message to another component which has been destroyed (which should unregister itself from EventBus on that time), it only triggered a norecipient waring
instead of crashing the app.
Also with EventBus
as intermedia, you can avoid to exposing objects to root activity or application just for registering callbacks on each other. Components are higher cohesion & lower coupling.
As the result, EventBus
saves tons of time to debugging crash, and make your code more readable, maintainble, extensible, and flexible.
Abusing EventBus
kills your app easily
“EventBus
is awesome! It is so convenient, so let’s replace everything with event”… This kind of saying is commonly heard from the developers who just realized the benefits from EventBus
. Since EventBus
is too convenient to use, they tends to replace everything with EventBus.
But we mentioned in the introduction of EventBus
that EventBus
is design to replace traditional event system in Java, and is not designed for general use. Abusing makes your code hard to understand, hard to debug. Long event chain is a common reason that cause of unexpected behavior.
Broadcast Event, Command and Request
EventBus
is powerful, but can be easily abused. To make a better use of EventBus, I learn a number of EventBus usages, and evaluated the scenario, and summarized out 3 typeical EventBus usage patterns: Broadcast Event, Command and Request.
Broadcast Event
Broadcast Event
is a special kind of event that used by a specific component to broadcast its status updated to other components.
Declaration
Broadcast Event
should be used when several components cares about the specific component’s status update. So usually Broadcast Event
should have more than one recipients or, at least, potential recipients.
Broadcast Event
should be an immutable data object, so:
- It is immutable, so once it is created, its status should not changed, which guarantees the equality between recipients.
- It is data object, so it should not has methods that might change other classes status.
- It might have methods that helps its consumer to consume the data it contains.
- It should be declared as a nested static class of publisher.
NOTICE
If you thought a Event is “Broadcast Event”, but later you found it has only one recipient, then you might need to consider refact it into a Command
or a Request
.
Command
Command
is a special kind of event that has the ability to update specific object or specific type of objects. In most cases, Command
should have only one recipient. In some special cases, it might has a group of recipients with exactly same type.
Precisely, the latter case is a variant of Command
pattern, Batch Command
, which works as same as Command
but have multiple recipients so it can update multiple instances in a batch.
Command
should be a immutable object that able to update specific object, so:
- It should have 1
execute
method with 1 parameter, which represents the target that the command updates. - When invoking execute method shouldn’t change its own status, so it does exactly same thing when applying it to multiple targets.
- It behavior should be stable across time, so its behavior won’t change when it is apply asynchronously.
- The object that
execute
method accepts is not necessarily to be the recipient. It could be the object that recipient holds or it has access to. - It should be declared as nested static class of the recipient.
- If recipient accepts multiple events, these events are recommended to derived from the same base class. So The recipient could subscribe to the base class, rather than every command.
NOTICECommand
can be seen as recipient’s special method that can be invoked without known recipient instance. So its behavior should fully contained in the class. The subscribing method on recipient should contain one line of code to invoke execute
method on command.
Request
Request
is a special kind of event that has the ability to accept data from another object. If the request has multiple recipients, to avoid ambiguous behavior, there should be only one of Request
‘s respond the request.
But there is one exception, that is for the request collects data from multiple objects, multiple objects might respond to the request. This special kind of Request
is called Collector
.
Request
should be a object that accept data from recipient, so:
- It should have
respond
method with 1 parameter, which represents the data the request asks for. - Request should contains enough information for the recipients to determine whether to respond the request.
- The recipients should check request’s status to determine whether it should respond request.
- The request can update the publisher directly in the
respond
method - It should be declared as nested class of publisher. If possible, also declare it as static, which will be helpful to simplify the tests.
- Request might has methods to help recipient to determine whether to respond the request.
NOTICERequest
can be seen as a special method that publisher exposes to a specific recipient, so the specific recipient can invoke the method to provide data. For Request
, you might need to aware that that sometimes request might not found proper recipient to respond. If the responder is not guaranteed to exist, then the publish to watch out no-recipent warning from EventBus.