One should strive for loosely coupled design in software development. Otto is great library for Android which keep objects loosely coupled but still allow them to communicate efficiently.
Otto provides very simple mechanism for event publishing/subscribing which is based on Java annotations like
@Produce. However, while events can be posted on Runtime using
post() method, subscriptions are compile time only.
In my recent project most of my objects/views were getting generated at runtime and I needed something which allows me to setup communication at runtime.
Otto was already included in my project and then I posted this question on stackoverflow for help. I got two interesting solutions there.
Lets discuss them one by one
####Solution 1 - Use different model objects each subscribing for a different event Clever! But, I see following problems with this model
- What if its not known that which events this object should subscribe to at object creation time.
- What if subscription rules state that this object should subscribe to multiple events ?
- Creating new variant for same model based on what message its receiving ? It sounds really messy !
####Solution 2 - Have a generic event and a event type in that then send this secret to everyone !! (SSsshhhhhh…) At first glance it seems like a neater solution and might be good enough for some situations, but
- Every message is sent to every object. First I smell performance problems, second I have to add extra code to ignore non-relevant messages in every object.
I propose following approach which is a improvement above Solution1 and Solution2. Instead of having different Model classes for different event types lets have different
EventDelegate for different events. These event delegate will just receive and event and pass them on to models(or views or anything else which is interested party for that matter).
A typical parent event delegate should look like this
Now that I mentioned that each event should have its own delegate here is what child class look like
OttoEventListener is an interface which receiving party should implement in order to receive required event.
Now each model can create as many different delegate objects on runtime and subscribe to relevant events and get notified of them like below
also they should be able to unsubscribe in runtime at will
Note that above functions can be called at runtime based on any rules that might apply. These rules can come from API, or they can be result of some other runtime operations.
While there is some amount of work, it provides a flexible and scalable way of subscribing Otto events at runtime.
This Demo App on
github demonstrates this mechanism. There are three different models, each of these model subscribe to events at runtime from
MainActivity based on certain rules(I have kept things extremely simple here but these rules can be as complicated).
There are 3 buttons in
MainActivity, each button emits an event which is captured by subscribed model and reflects it in logs.
MultiEventModel shows that how this framework can even be used for subscribing to multiple events at runtime with little help from
Here is a class diagram from same repository to summarize everything
Here I have kept one
OttoEventDelegate object in each
Model for simplicity, but, A list can kept and handled as per use case. As many delegate objects can be added in that list enabling
Model to subscribe to as many events at runtime.
Happy Coding !!