Omnibus is a small, fast, clean Data Bus for Android, allowing the construction of loosely-coupled apps. With omnibus, you don't have to worry about things like manually unregistering Listeners, Activity leaks, or the problems that can occur with AsyncTask on a device rotate, for example.
Activities and Fragments subscribe to receive values of a certain type:
bus.subscribe(User.class, new Subscriber<User>() {
public void receive(User user) {
doSomething(user);
}
});
and those values are published to the bus either by a simple publish:
bus.publish(user);
or via a Provider:
bus.publish(User.class, new Provider<User>() {
public void provide(Subscriber<T> subscriber, String[] params) {
subscriber.receive(user);
}
});
Note that there is no simple 'get' method to return a value from the Bus - a Subscriber is always required. This encourages a style of programming where the calling code makes less assumptions about which order things happen in, which leads to more robust code. It doesn't matter which order publish/subscribe happen in, the Bus will ensure that all Subscribers receive the published value. This style also means you worry less about what is initialised when and you can focus on the real logic of your app.
See the demo directory for a simple demo app.
Anywhere you need to share data between different parts of your app. The most common way is to implement Providers for external (web) APIs that your app calls, and have your Activities/Fragments subscribe to them. Other good examples are Navigation & Preferences.
Activities and Fragments should call Bus.attach(this) and Bus.detach(this), usually in onResume() and onPause(). That's it. Bus.attach() can also be called in onCreate() if needed (attaching twice is harmless).
Subscribers are always called on the main UI thread. Providers are called synchronously, but asynchronous Providers are very easy to implement: start an AsyncTask in the provide() method and call subscriber.receive() in the onPostExecute(). Or you can use AsyncProvider, which does the AsyncTask for you:
bus.publish(User.class, new AsyncProvider<User>() {
public User retrieveValue(String[] params) {
return doSomeNetworkCall();
}
});
Each Activity or Fragment gets its own BusContext when it calls Bus.attach(). The BusContext cleans up all the Subscribers when onDetach() is called. Providers and Values posted to the bus via publish() are app-scope, but there will be only one provider or value per class. Using channels allows you to have more than one per class (see below), but the intention here is that the number of channels is small. The main rule to remember is never implement a Provider that has a reference to an Activity. Providers are passed the Application Context when they are invoked, so there is no need to use an Activity to get a Context.
There are two ways to do this:
- It's possible to pass a String array of parameters via request(Class, String[])
- Providers can pull their parameters from the bus
update(T value) allows you to pass a value for update to a Provider. The Provider's update(T) method is called, and it can then publish the new value, either directly, or by getting it from the external API. The AsyncProvider convenience class has an updateValue() method that you can override to implement the actual operation (it gets called in a background thread).
If you really need this, you can publish & subscribe using the extra optional 'channelId' String parameter. An alternative is to create a few wrapper classes for the different values.
Calling invalidate(Class) will force the Provider to provide a new value, or simply clear the value from the Bus if there is no Provider.
Omnibus doesn't use reflection or annotations, so it's extremely fast
contact: [email protected]