import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
public class EventBus {
private static volatile EventBus defaultInstance;
private final HashMap<Class<?>, ArrayList<SubscriberMethod>> events;
private EventBus() {
events = new HashMap<Class<?>, ArrayList<SubscriberMethod>>();
}
public static EventBus instance() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
public void register(Object subscriber, Class<?> eventType) throws NoSuchMethodException {
register(subscriber, "onEvent", eventType);
}
public synchronized void register(Object subscriber, String method, Class<?> eventType)
throws NoSuchMethodException {
SubscriberMethod subscriberMethod = getSubscriberMethod(subscriber, method, eventType);
if (events.containsKey(eventType)) {
events.get(eventType).add(subscriberMethod);
} else {
ArrayList<SubscriberMethod> methods = new ArrayList<SubscriberMethod>();
methods.add(subscriberMethod);
events.put(eventType, methods);
}
}
public void unregister(Object subscriber, Class<?> eventType) throws NoSuchMethodException {
unregister(subscriber, "onEvent", eventType);
}
public synchronized void unregister(Object subscriber, String method, Class<?> eventType)
throws NoSuchMethodException {
if (events.containsKey(eventType)) {
SubscriberMethod sm = getSubscriberMethod(subscriber, method, eventType);
ArrayList<SubscriberMethod> list = events.get(eventType);
Iterator<SubscriberMethod> iterator = list.iterator();
while (iterator.hasNext()) {
SubscriberMethod subscriberMethod = iterator.next();
if (subscriberMethod.equals(sm)) {
iterator.remove();
}
}
}
}
private SubscriberMethod getSubscriberMethod(Object subscriber, String method,
Class<?> eventType) throws NoSuchMethodException {
Method m = subscriber.getClass().getDeclaredMethod(method, eventType);
if (!m.isAccessible()) {
m.setAccessible(true);
}
return new SubscriberMethod(subscriber, m, eventType);
}
public void post(Object event) {
try {
ArrayList<SubscriberMethod> list = events.get(event.getClass());
if (list != null) {
Iterator<SubscriberMethod> iterator = list.iterator();
while (iterator.hasNext()) {
SubscriberMethod sm = iterator.next();
sm.method.invoke(sm.subscriber, event);
}
}
} catch (Exception e) {
Log.e("EventBus post error", e);
}
}
}
import java.lang.reflect.Method;
final class SubscriberMethod {
final Object subscriber;
final Method method;
final Class<?> eventType;
/** Used for efficient comparison */
String methodString;
SubscriberMethod(Object subscriber, Method method, Class<?> eventType) {
this.subscriber = subscriber;
this.method = method;
this.eventType = eventType;
}
@Override
public boolean equals(Object other) {
if (other instanceof SubscriberMethod) {
checkMethodString();
SubscriberMethod otherSubscriberMethod = (SubscriberMethod) other;
otherSubscriberMethod.checkMethodString();
// Don't use method.equals because of
// http://code.google.com/p/android/issues/detail?id=7811#c6
return methodString.equals(otherSubscriberMethod.methodString);
} else {
return false;
}
}
private synchronized void checkMethodString() {
if (methodString == null) {
// Method.toString has more overhead, just take relevant parts of
// the method
StringBuilder builder = new StringBuilder(128);
builder.append(subscriber.getClass().getName());
builder.append('#').append(method.getName());
builder.append('(').append(eventType.getName());
methodString = builder.toString();
}
}
}