package com.datdo.mobilib.event; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import com.datdo.mobilib.event.MblWeakArrayList.MblWeakArrayListCallback; import com.datdo.mobilib.util.MblUtils; /** * <pre> * Class to post in-app events between objects. * This class keeps a {@link WeakReference} to listeners to prevent memory leak. * If you want to create an anonymous listener, please use {@link MblStrongEventListener}, otherwise the listener will be destroyed by GC. * </pre> */ public class MblEventCenter { private static final Map<String, MblWeakArrayList<MblEventListener>> sEventListenerMap = new ConcurrentHashMap<String, MblWeakArrayList<MblEventListener>>(); /** * <pre> * Register a listener for multiple events. * </pre> * @param names event names */ public static void addListener(MblEventListener listener, String[] names) { if (!MblUtils.isEmpty(names)) { for (String n : names) { addListener(listener, n); } } } /** * <pre> * Register a listener for one event. * </pre> * @param name */ public static void addListener(MblEventListener listener, String name) { MblWeakArrayList<MblEventListener> listeners = null; if(sEventListenerMap.containsKey(name)) { listeners = sEventListenerMap.get(name); } else { listeners = new MblWeakArrayList<MblEventListener>(); sEventListenerMap.put(name, listeners); } if(listeners.contains(listener)) return; listeners.add(listener); } /** * <pre> * Remove listener from one event * </pre> * @param name event name */ public static void removeListenerFromEvent(MblEventListener listener, String name) { if(!sEventListenerMap.containsKey(name)) return; MblWeakArrayList<MblEventListener> listeners = null; listeners = sEventListenerMap.get(name); if(!listeners.contains(listener)) return; listeners.remove(listener); if(listeners.isEmpty()) { sEventListenerMap.remove(name); } } /** * <pre> * Remove listener from all events. * </pre> */ public static void removeListenerFromAllEvents(MblEventListener listener) { Set<String> keys = sEventListenerMap.keySet(); for (String aKey : keys) { removeListenerFromEvent(listener, aKey); } } /** * <pre> * Post event to all listeners. * The callback method {@link MblEventListener#onEvent(Object, String, Object...)} is invoked in main thread. * </pre> * @param sender object that posts the event * @param name event name * @param args data attached to event */ public static void postEvent(final Object sender, final String name, final Object... args) { if(!sEventListenerMap.containsKey(name)) return; MblWeakArrayList<MblEventListener> listeners; listeners = sEventListenerMap.get(name); final List<Runnable> actions = new ArrayList<Runnable>(); listeners.iterateWithCallback(new MblWeakArrayListCallback<MblEventListener>() { @Override public void onInterate(final MblEventListener listener) { actions.add(new Runnable() { @Override public void run() { listener.onEvent(sender, name, args); } }); } }); for (Runnable r : actions) { MblUtils.executeOnMainThread(r); } } /** * <pre> * Get argument object from argument array safely (no {@link NullPointerException} or {@link IndexOutOfBoundsException}) * This method is designated for {@link MblEventListener#onEvent(Object, String, Object...)} * </pre> * @param index specific index of argument * @param args argument array * @return argument object if index is valid, otherwise return null */ public static Object getArgAt(int index, Object...args) { return args != null && args.length > index ? args[index] : null; } }