diff --git a/otto/src/main/java/com/squareup/otto/AnnotatedHandlerFinder.java b/otto/src/main/java/com/squareup/otto/AnnotatedHandlerFinder.java index 7d79b71..386ce29 100644 --- a/otto/src/main/java/com/squareup/otto/AnnotatedHandlerFinder.java +++ b/otto/src/main/java/com/squareup/otto/AnnotatedHandlerFinder.java @@ -130,8 +130,7 @@ private static void loadAnnotatedMethods(Class listenerClass, } /** This implementation finds all methods marked with a {@link Produce} annotation. */ - static Map, EventProducer> findAllProducers(Object listener) { - final Class listenerClass = listener.getClass(); + static Map, EventProducer> findAllProducers(Object listener, Class listenerClass) { Map, EventProducer> handlersInMethod = new HashMap, EventProducer>(); Map, Method> methods = PRODUCERS_CACHE.get(listenerClass); @@ -150,8 +149,7 @@ static Map, EventProducer> findAllProducers(Object listener) { } /** This implementation finds all methods marked with a {@link Subscribe} annotation. */ - static Map, Set> findAllSubscribers(Object listener) { - Class listenerClass = listener.getClass(); + static Map, Set> findAllSubscribers(Object listener, Class listenerClass) { Map, Set> handlersInMethod = new HashMap, Set>(); Map, Set> methods = SUBSCRIBERS_CACHE.get(listenerClass); diff --git a/otto/src/main/java/com/squareup/otto/Bus.java b/otto/src/main/java/com/squareup/otto/Bus.java index 0ab6620..3ac83c6 100644 --- a/otto/src/main/java/com/squareup/otto/Bus.java +++ b/otto/src/main/java/com/squareup/otto/Bus.java @@ -178,16 +178,43 @@ public Bus(ThreadEnforcer enforcer, String identifier) { * If any producers are registering for types which already have subscribers, each subscriber will be called with * the value from the result of calling the producer. * - * @param object object whose handler methods should be registered. - * @throws NullPointerException if the object is null. + * @param object object whose producer and handler methods should be registered. + * @throws NullPointerException if {@code object} is null. */ public void register(Object object) { if (object == null) { throw new NullPointerException("Object to register must not be null."); } + register(object, object.getClass()); + } + + /** + * Registers all handler methods on {@code object} to receive events and producer methods to provide events. + *

+ * If any subscribers are registering for types which already have a producer they will be called immediately + * with the result of calling that producer. + *

+ * If any producers are registering for types which already have subscribers, each subscriber will be called with + * the value from the result of calling the producer. + * + * @param object object used to trigger registered producer and handler methods. The {@code object}s class must be + * assignable to objects of the type {@code listenerClass}. + * @param listenerClass class whose producer and handler methods should be registered. + * @throws NullPointerException if {@code object} or {@code listenerClass} is null. + */ + public void register(Object object, Class listenerClass) { + if (object == null) { + throw new NullPointerException("Object to trigger register methods not be null."); + } + if (listenerClass == null) { + throw new NullPointerException("Class to register must not be null."); + } + if (!listenerClass.isAssignableFrom(object.getClass())) { + throw new IllegalArgumentException("Class to unregister must be an instance of or assignable from Object class."); + } enforcer.enforce(this); - Map, EventProducer> foundProducers = handlerFinder.findAllProducers(object); + Map, EventProducer> foundProducers = handlerFinder.findAllProducers(object, listenerClass); for (Class type : foundProducers.keySet()) { final EventProducer producer = foundProducers.get(type); @@ -206,7 +233,7 @@ public void register(Object object) { } } - Map, Set> foundHandlersMap = handlerFinder.findAllSubscribers(object); + Map, Set> foundHandlersMap = handlerFinder.findAllSubscribers(object, listenerClass); for (Class type : foundHandlersMap.keySet()) { Set handlers = handlersByType.get(type); if (handlers == null) { @@ -258,15 +285,37 @@ private void dispatchProducerResultToHandler(EventHandler handler, EventProducer * * @param object object whose producer and handler methods should be unregistered. * @throws IllegalArgumentException if the object was not previously registered. - * @throws NullPointerException if the object is null. + * @throws NullPointerException if {@code object} is null. */ public void unregister(Object object) { if (object == null) { throw new NullPointerException("Object to unregister must not be null."); } + unregister(object, object.getClass()); + } + + /** + * Unregisters all producer and handler methods on a registered {@code object}. + * + * @param object object used to trigger registered producer and handler methods. The {@code object}s class must be + * assignable to objects of the type {@code listenerClass}. + * @param listenerClass class whose producer and handler methods should be unregistered. + * @throws IllegalArgumentException if the object was not previously registered. + * @throws NullPointerException if {@code object} or {@code listenerClass} is null. + */ + public void unregister(Object object, Class listenerClass) { + if (object == null) { + throw new NullPointerException("Object to trigger register methods not be null."); + } + if (listenerClass == null) { + throw new NullPointerException("Class to unregister must not be null."); + } + if (!listenerClass.isAssignableFrom(object.getClass())) { + throw new IllegalArgumentException("Class to unregister must be an instance of or assignable from Object class."); + } enforcer.enforce(this); - Map, EventProducer> producersInListener = handlerFinder.findAllProducers(object); + Map, EventProducer> producersInListener = handlerFinder.findAllProducers(object, listenerClass); for (Map.Entry, EventProducer> entry : producersInListener.entrySet()) { final Class key = entry.getKey(); EventProducer producer = getProducerForEventType(key); @@ -274,20 +323,20 @@ public void unregister(Object object) { if (value == null || !value.equals(producer)) { throw new IllegalArgumentException( - "Missing event producer for an annotated method. Is " + object.getClass() + "Missing event producer for an annotated method. Is " + listenerClass + " registered?"); } producersByType.remove(key).invalidate(); } - Map, Set> handlersInListener = handlerFinder.findAllSubscribers(object); + Map, Set> handlersInListener = handlerFinder.findAllSubscribers(object, listenerClass); for (Map.Entry, Set> entry : handlersInListener.entrySet()) { Set currentHandlers = getHandlersForEventType(entry.getKey()); Collection eventMethodsInListener = entry.getValue(); if (currentHandlers == null || !currentHandlers.containsAll(eventMethodsInListener)) { throw new IllegalArgumentException( - "Missing event handler for an annotated method. Is " + object.getClass() + "Missing event handler for an annotated method. Is " + listenerClass + " registered?"); } diff --git a/otto/src/main/java/com/squareup/otto/HandlerFinder.java b/otto/src/main/java/com/squareup/otto/HandlerFinder.java index ff61a2c..956ff0a 100644 --- a/otto/src/main/java/com/squareup/otto/HandlerFinder.java +++ b/otto/src/main/java/com/squareup/otto/HandlerFinder.java @@ -22,20 +22,20 @@ /** Finds producer and subscriber methods. */ interface HandlerFinder { - Map, EventProducer> findAllProducers(Object listener); - - Map, Set> findAllSubscribers(Object listener); + Map, EventProducer> findAllProducers(Object listener, Class targetClass); + Map, Set> findAllSubscribers(Object listener, Class targetClass); HandlerFinder ANNOTATED = new HandlerFinder() { + @Override - public Map, EventProducer> findAllProducers(Object listener) { - return AnnotatedHandlerFinder.findAllProducers(listener); + public Map, EventProducer> findAllProducers(Object listener, Class targetClass) { + return AnnotatedHandlerFinder.findAllProducers(listener, targetClass); } @Override - public Map, Set> findAllSubscribers(Object listener) { - return AnnotatedHandlerFinder.findAllSubscribers(listener); + public Map, Set> findAllSubscribers(Object listener, Class targetClass) { + return AnnotatedHandlerFinder.findAllSubscribers(listener, targetClass); } }; } diff --git a/otto/src/test/java/com/squareup/otto/UnregisteringHandlerTest.java b/otto/src/test/java/com/squareup/otto/UnregisteringHandlerTest.java index 50b9990..694470e 100644 --- a/otto/src/test/java/com/squareup/otto/UnregisteringHandlerTest.java +++ b/otto/src/test/java/com/squareup/otto/UnregisteringHandlerTest.java @@ -98,13 +98,13 @@ public int compare(EventHandler eventHandler, EventHandler eventHandler1) { }; @Override - public Map, EventProducer> findAllProducers(Object listener) { - return HandlerFinder.ANNOTATED.findAllProducers(listener); + public Map, EventProducer> findAllProducers(Object listener, Class targetClass) { + return HandlerFinder.ANNOTATED.findAllProducers(listener, targetClass); } @Override - public Map, Set> findAllSubscribers(Object listener) { - Map, Set> found = HandlerFinder.ANNOTATED.findAllSubscribers(listener); + public Map, Set> findAllSubscribers(Object listener, Class targetClass) { + Map, Set> found = HandlerFinder.ANNOTATED.findAllSubscribers(listener, targetClass); Map, Set> sorted = new HashMap, Set>(); for (Map.Entry, Set> entry : found.entrySet()) { SortedSet handlers = new TreeSet(handlerComparator);