Ensure onEvents is called when listener is removed.
When a listener is removed or released we may not have called onEvents for events that happened before this point. To ensure listeners don't miss events we need to trigger a final onEvents with all events we have happened so far (if any). PiperOrigin-RevId: 346553030
This commit is contained in:
parent
e7f5912677
commit
f18d81f8a8
@ -156,7 +156,7 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
public void remove(T listener) {
|
public void remove(T listener) {
|
||||||
for (ListenerHolder<T, E> listenerHolder : listeners) {
|
for (ListenerHolder<T, E> listenerHolder : listeners) {
|
||||||
if (listenerHolder.listener.equals(listener)) {
|
if (listenerHolder.listener.equals(listener)) {
|
||||||
listenerHolder.release();
|
listenerHolder.release(iterationFinishedEvent);
|
||||||
listeners.remove(listenerHolder);
|
listeners.remove(listenerHolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,7 +221,7 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
*/
|
*/
|
||||||
public void release() {
|
public void release() {
|
||||||
for (ListenerHolder<T, E> listenerHolder : listeners) {
|
for (ListenerHolder<T, E> listenerHolder : listeners) {
|
||||||
listenerHolder.release();
|
listenerHolder.release(iterationFinishedEvent);
|
||||||
}
|
}
|
||||||
listeners.clear();
|
listeners.clear();
|
||||||
released = true;
|
released = true;
|
||||||
@ -245,6 +245,7 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
@Nonnull public final T listener;
|
@Nonnull public final T listener;
|
||||||
|
|
||||||
private E eventsFlags;
|
private E eventsFlags;
|
||||||
|
private boolean needsIterationFinishedEvent;
|
||||||
private boolean released;
|
private boolean released;
|
||||||
|
|
||||||
public ListenerHolder(@Nonnull T listener, Supplier<E> eventFlagSupplier) {
|
public ListenerHolder(@Nonnull T listener, Supplier<E> eventFlagSupplier) {
|
||||||
@ -252,26 +253,31 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
this.eventsFlags = eventFlagSupplier.get();
|
this.eventsFlags = eventFlagSupplier.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void release() {
|
public void release(IterationFinishedEvent<T, E> event) {
|
||||||
released = true;
|
released = true;
|
||||||
|
if (needsIterationFinishedEvent) {
|
||||||
|
event.invoke(listener, eventsFlags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invoke(int eventFlag, Event<T> event) {
|
public void invoke(int eventFlag, Event<T> event) {
|
||||||
if (!released) {
|
if (!released) {
|
||||||
event.invoke(listener);
|
|
||||||
if (eventFlag != C.INDEX_UNSET) {
|
if (eventFlag != C.INDEX_UNSET) {
|
||||||
eventsFlags.add(eventFlag);
|
eventsFlags.add(eventFlag);
|
||||||
}
|
}
|
||||||
|
needsIterationFinishedEvent = true;
|
||||||
|
event.invoke(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void iterationFinished(
|
public void iterationFinished(
|
||||||
Supplier<E> eventFlagSupplier, IterationFinishedEvent<T, E> event) {
|
Supplier<E> eventFlagSupplier, IterationFinishedEvent<T, E> event) {
|
||||||
if (!released) {
|
if (!released && needsIterationFinishedEvent) {
|
||||||
// Reset flags before invoking the listener to ensure we keep all new flags that are set by
|
// Reset flags before invoking the listener to ensure we keep all new flags that are set by
|
||||||
// recursive events triggered from this callback.
|
// recursive events triggered from this callback.
|
||||||
E flagToNotify = eventsFlags;
|
E flagToNotify = eventsFlags;
|
||||||
eventsFlags = eventFlagSupplier.get();
|
eventsFlags = eventFlagSupplier.get();
|
||||||
|
needsIterationFinishedEvent = false;
|
||||||
event.invoke(listener, flagToNotify);
|
event.invoke(listener, flagToNotify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,10 +297,11 @@ public class ListenerSetTest {
|
|||||||
// Listener2 shouldn't even get this event as it's removed before the event can be invoked.
|
// Listener2 shouldn't even get this event as it's removed before the event can be invoked.
|
||||||
listenerSet.sendEvent(EVENT_ID_1, TestListener::callback1);
|
listenerSet.sendEvent(EVENT_ID_1, TestListener::callback1);
|
||||||
listenerSet.remove(listener1);
|
listenerSet.remove(listener1);
|
||||||
listenerSet.sendEvent(EVENT_ID_1, TestListener::callback1);
|
listenerSet.sendEvent(EVENT_ID_2, TestListener::callback2);
|
||||||
ShadowLooper.runMainLooperToNextTask();
|
ShadowLooper.runMainLooperToNextTask();
|
||||||
|
|
||||||
verify(listener1).callback1();
|
verify(listener1).callback1();
|
||||||
|
verify(listener1).iterationFinished(Flags.create(EVENT_ID_1));
|
||||||
verifyNoMoreInteractions(listener1, listener2);
|
verifyNoMoreInteractions(listener1, listener2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,6 +349,7 @@ public class ListenerSetTest {
|
|||||||
ShadowLooper.runMainLooperToNextTask();
|
ShadowLooper.runMainLooperToNextTask();
|
||||||
|
|
||||||
verify(listener1).callback1();
|
verify(listener1).callback1();
|
||||||
|
verify(listener1).iterationFinished(Flags.create(EVENT_ID_1));
|
||||||
verifyNoMoreInteractions(listener1, listener2);
|
verifyNoMoreInteractions(listener1, listener2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user