Skip to content

Instantly share code, notes, and snippets.

@naphaso
Created October 18, 2013 00:53
Show Gist options
  • Save naphaso/c9dbb8a4d4035d1f0584 to your computer and use it in GitHub Desktop.
Save naphaso/c9dbb8a4d4035d1f0584 to your computer and use it in GitHub Desktop.
import android.os.Handler;
import android.os.Looper;
import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
/**
* User: Stanislav Ovsyannikov
* Date: 7/31/13
* Time: 6:30 PM
*/
@Singleton
public class GlobalEventManager {
private static final Logger logger = LoggerFactory.getLogger(GlobalEventManager.class);
// thread pools
private final EventManagerThreadPoolExecutor threadPoolExecutor =
new EventManagerThreadPoolExecutor(10, 10, 15, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
private final ScheduledExecutorService scheduler =
new ScheduledThreadPoolExecutor(1, new EventManagerSchedulerThreadFactory());
private final Handler handler = new Handler(Looper.getMainLooper());
private final Map<Class<?>, Set<EventListener>> listeners = new HashMap<Class<?>, Set<EventListener>>();
private final Map<TimerListener, ScheduledFuture<?>> schduledFutures = new HashMap<TimerListener, ScheduledFuture<?>>();
public void registerListeners(final Object o) {
try {
final Method[] methods = o.getClass().getDeclaredMethods();
for(final Method method : methods) {
final Event eventAnnotation = method.getAnnotation(Event.class);
if(eventAnnotation != null) {
final EventListener listener = new EventListener(o, method, method.getParameterTypes()[0], eventAnnotation.value());
synchronized (this) {
if(!listeners.containsKey(listener.eventType)) {
Set<EventListener> eventListenerList = new LinkedHashSet<EventListener>();
eventListenerList.add(listener);
listeners.put(listener.eventType, eventListenerList);
} else {
listeners.get(listener.eventType).add(listener);
}
}
}
final EventTimer eventTimerAnnotation = method.getAnnotation(EventTimer.class);
if(eventTimerAnnotation != null) {
final TimerListener listener = new TimerListener(o, method);
final ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(listener, eventTimerAnnotation.value(), eventTimerAnnotation.value(), MILLISECONDS);
synchronized (this) {
schduledFutures.put(listener, future);
}
}
}
} catch (Exception e) {
logger.error("exception on register listeners", e);
}
}
public void unregisterListeners(final Object o) {
try {
final Method[] methods = o.getClass().getDeclaredMethods();
for(final Method method : methods) {
final Event eventAnnotation = method.getAnnotation(Event.class);
if(eventAnnotation != null) {
final EventListener listener = new EventListener(o, method, method.getParameterTypes()[0], eventAnnotation.value());
synchronized (this) {
if(!listeners.containsKey(listener.eventType)) {
logger.error("try to unregister unexisting listener");
} else {
if (!listeners.get(listener.eventType).remove(listener)) {
logger.error("unable to find class to unregister");
}
}
}
}
final EventTimer eventTimerAnnotation = method.getAnnotation(EventTimer.class);
if(eventTimerAnnotation != null) {
final TimerListener listener = new TimerListener(o, method);
synchronized (this) {
final ScheduledFuture<?> future = schduledFutures.get(listener);
future.cancel(false);
}
}
}
} catch (Exception e) {
logger.error("exception on unregister listeners", e);
}
}
public void fire(Object event) {
logger.info("fire event " + event.getClass().getSimpleName());
try {
List<EventListener> eventListenerList = null;
synchronized (this) {
final Set<EventListener> eventListeners = listeners.get(event.getClass());
if(eventListeners != null)
eventListenerList = new ArrayList<EventListener>(eventListeners);
}
if(eventListenerList != null) {
final Iterator<EventListener> iterator = eventListenerList.iterator();
List<EventListener> toRemove = null;
while(iterator.hasNext()) {
final EventListener eventListener = iterator.next();
if(!eventListener.isValid()) {
if(toRemove == null)
toRemove = new ArrayList<EventListener>(10);
toRemove.add(eventListener);
continue;
}
switch(eventListener.type) {
case IN:
eventListener.run(event);
break;
case TP:
threadPoolExecutor.submit(new EventTask(eventListener, event));
break;
case UI:
handler.post(new EventTask(eventListener, event));
break;
}
}
if(toRemove != null) {
logger.debug("force remove {} dead event listeners", toRemove.size());
synchronized (this) {
final Set<EventListener> eventListeners = listeners.get(event.getClass());
eventListeners.removeAll(toRemove);
}
}
}
} catch (Exception e) {
logger.error("exception on event processing", e);
}
}
}
@marwinxxii
Copy link

I can't comment on habrahabr, but want to share an already existing library for this case
http://square.github.io/otto/

Features:

  • Annotations to mark event handlers
  • Event producers
  • Ability to create multiple buses

and another library
https://github.com/greenrobot/EventBus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment