Created
June 25, 2018 10:52
-
-
Save instantiator/6cdc970ea984bf9855b8fed5dff27030 to your computer and use it in GitHub Desktop.
WeakEventProvider
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.flt.example.eventproviders; | |
import com.flt.aislethree.sharedservicelib.logging.Log; | |
import java.lang.ref.WeakReference; | |
import java.util.EventListener; | |
import java.util.LinkedList; | |
import java.util.List; | |
/** | |
* The WeakEventProvider allows you to link listeners from your transient | |
* objects (such as Activities and Fragments) to a source of events. The | |
* WeakEventProvider only holds a weak pointer to the listener, and so | |
* does not prevent it from being garbage collected. If it finds nulls | |
* where listeners should be, it handles this gracefully by removing them | |
* from its listeners collection. | |
*/ | |
public class WeakEventProvider<EventType> { | |
protected String TAG; | |
protected List<WeakReference<Listener<EventType>>> listeners; | |
protected EventType sticky; | |
public WeakEventProvider() { | |
this.TAG = getClass().getSimpleName(); | |
this.listeners = new LinkedList<>(); | |
} | |
public synchronized void notifyListenersSticky(EventType event) { | |
this.sticky = event; | |
notifyListeners(event); | |
} | |
public synchronized void clearSticky() { | |
this.sticky = null; | |
} | |
public synchronized void notifyListeners(EventType event) { | |
List<WeakReference<Listener<EventType>>> toRemove = new LinkedList<>(); | |
for (WeakReference<Listener<EventType>> reference : listeners) { | |
Listener<EventType> listener = reference.get(); | |
if (listener != null) { | |
boolean completed; | |
try { | |
completed = listener.onNotifyEvent(event); | |
} catch (Exception e) { | |
Log.e(TAG, "Exception encountered notifying listener. Removing listener."); | |
completed = true; // | |
} | |
if (completed) { | |
toRemove.add(reference); | |
} | |
} else { | |
toRemove.add(reference); | |
} | |
} | |
listeners.removeAll(toRemove); | |
} | |
public synchronized void cleanDeadRefs() { | |
List<WeakReference<Listener<EventType>>> toRemove = new LinkedList<>(); | |
for (WeakReference<Listener<EventType>> reference : listeners) { | |
if (reference.get() == null) { | |
toRemove.add(reference); | |
} | |
} | |
listeners.removeAll(toRemove); | |
} | |
public void requestSticky(Listener<EventType> listener) { | |
if (hasSticky()) { listener.onNotifyEvent(sticky); } | |
} | |
public synchronized void addListener(Listener<EventType> listener) { | |
boolean alreadyListening = false; | |
for (WeakReference<Listener<EventType>> reference : listeners) { | |
if (reference.get() == listener) { | |
alreadyListening = true; | |
break; | |
} | |
} | |
if (!alreadyListening) { | |
listener.reset(); | |
listeners.add(new WeakReference<Listener<EventType>>(listener)); | |
} | |
// always notify with the sticky state - even if the add is redundant | |
if (hasSticky()) { listener.onNotifyEvent(sticky); } | |
} | |
public boolean hasSticky() { return sticky != null; } | |
public synchronized void removeListener(Listener<EventType> listener) { | |
List<WeakReference<Listener<EventType>>> toRemove = new LinkedList<>(); | |
for (WeakReference<Listener<EventType>> reference : listeners) { | |
if (reference.get() == listener || reference.get() == null) { | |
toRemove.add(reference); | |
break; | |
} | |
} | |
listeners.removeAll(toRemove); | |
} | |
public static abstract class Listener<E> { | |
public boolean completed = false; | |
public boolean onNotifyEvent(E event) { | |
if (!completed) { | |
completed = parseEvent(event); | |
} | |
return completed; | |
} | |
/** | |
* @return true if this event was accepted and the listener should stop listening, | |
* false to remain a listener. | |
*/ | |
protected abstract boolean parseEvent(E event); | |
public void complete() { | |
completed = true; | |
} | |
public void reset() { | |
completed = false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment