I'm using Otto as my event bus in my android application.
I had to make sure that certain events are called in the main thread, or not in the main thread, for that I created my own bus class which uses Otto like so:
class MyEventBus {
private final Bus anyThreadBus;
private final Bus mainThreadBus;
private final Bus notMainThreadBus;
private final Handler mainThreadHandler;
public enum Strategy {
Any,
Main,
NotMain
}
MyEventBus() {
this.anyThreadBus = new Bus(ThreadEnforcer.ANY);
this.mainThreadBus = new Bus(ThreadEnforcer.MAIN);
this.notMainThreadBus = new Bus(ThreadEnforcer.ANY);
this.mainThreadHandler = new Handler(Looper.getMainLooper());
}
public void register(Object object) {
this.register(object, Strategy.Any);
}
public void register(Object object, Strategy strategy) {
switch (strategy) {
case Main:
this.mainThreadBus.register(object);
break;
case NotMain:
this.notMainThreadBus.register(object);
break;
case Any:
default:
this.anyThreadBus.register(object);
}
}
public void unregister(Object object) {
try {
this.anyThreadBus.unregister(object);
} catch (Exception e) {}
try {
this.mainThreadBus.unregister(object);
} catch (Exception e) {}
try {
this.notMainThreadBus.unregister(object);
} catch (Exception e) {}
}
public void post(Object event) {
this.anyThreadBus.post(event);
this.enforceOnMainThread(event);
this.enforceOnNotMainThread(event);
}
public void post(Object event, Strategy strategy) {
switch (strategy) {
case Main:
this.enforceOnMainThread(event);
break;
case NotMain:
this.enforceOnNotMainThread(event);
break;
case Any:
default:
this.anyThreadBus.post(event);
}
}
private void enforceOnNotMainThread(final Object event) {
if (MyEventBus.onMainThread()) {
// MyApplication.pool() returns a shared thread pool for the application
MyApplication.pool().execute(new Runnable() {
@Override
public void run() {
notMainThreadBus.post(event);
}
});
} else {
this.notMainThreadBus.post(event);
}
}
private void enforceOnMainThread(final Object event) {
if (MyEventBus.onMainThread()) {
this.mainThreadBus.post(event);
} else {
this.mainThreadHandler.post(new Runnable() {
@Override
public void run() {
mainThreadBus.post(event);
}
});
}
}
private static boolean onMainThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
}
I have two questions:
In my post methods I post the event on all of the 3 buses, and that's because I don't know if the posted event has a registered class in a certain bus. Is there a way to know? something like:
if (this.anyThreadBus.has(event)) { ... }
Is there a way to do this other than maintaining a map of event classes to registered classes per bus?Currently each registered class has an enforcement per call it made to
register
. But it would be best if I couldn't specify the enforcement per method and not for the entire class, something like:
@Subscribe(enforcement = Strategy.Main) public void handleMyEvent(MyEvent event) { ... }
Can that be done somehow?
Thanks.