From 13e0513ea3efd6385d4cddbaca47a43807d486aa Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 23 Oct 2018 06:23:50 -0700 Subject: [PATCH] Give EventDispatcher more predictable behavior If EventDispatcher.removeListener is called to remove a listener, and if the call is made from the same thread that said listener handles events on, then it should be guaranteed that the listener will not be subsequently invoked on that thread. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=218331427 --- .../exoplayer2/util/EventDispatcher.java | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/EventDispatcher.java b/library/core/src/main/java/com/google/android/exoplayer2/util/EventDispatcher.java index 26c02d8ae9..07f278c808 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/EventDispatcher.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/EventDispatcher.java @@ -39,22 +39,23 @@ public final class EventDispatcher { /** The list of listeners and handlers. */ private final CopyOnWriteArrayList> listeners; - /** Creates event dispatcher. */ + /** Creates an event dispatcher. */ public EventDispatcher() { listeners = new CopyOnWriteArrayList<>(); } - /** Adds listener to event dispatcher. */ + /** Adds a listener to the event dispatcher. */ public void addListener(Handler handler, T eventListener) { Assertions.checkArgument(handler != null && eventListener != null); removeListener(eventListener); listeners.add(new HandlerAndListener<>(handler, eventListener)); } - /** Removes listener from event dispatcher. */ + /** Removes a listener from the event dispatcher. */ public void removeListener(T eventListener) { for (HandlerAndListener handlerAndListener : listeners) { if (handlerAndListener.listener == eventListener) { + handlerAndListener.release(); listeners.remove(handlerAndListener); } } @@ -67,19 +68,33 @@ public final class EventDispatcher { */ public void dispatch(Event event) { for (HandlerAndListener handlerAndListener : listeners) { - T eventListener = handlerAndListener.listener; - handlerAndListener.handler.post(() -> event.sendTo(eventListener)); + handlerAndListener.dispatch(event); } } private static final class HandlerAndListener { - public final Handler handler; - public final T listener; + private final Handler handler; + private final T listener; + + private boolean released; public HandlerAndListener(Handler handler, T eventListener) { this.handler = handler; this.listener = eventListener; } + + public void release() { + released = true; + } + + public void dispatch(Event event) { + handler.post( + () -> { + if (!released) { + event.sendTo(listener); + } + }); + } } }