簡易EventBus實現
阿新 • • 發佈:2019-02-18
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(); } } }