Clarify docs around listener hierarchies in MediaSourceEventDispatcher
Also add a couple of tests to enforce the documentation. PiperOrigin-RevId: 301796102
This commit is contained in:
parent
818925d4a7
commit
181177a245
@ -103,6 +103,11 @@ public class MediaSourceEventDispatcher {
|
|||||||
* event dispatched to {@code listenerClass} will only be passed to the {@code eventListener}
|
* event dispatched to {@code listenerClass} will only be passed to the {@code eventListener}
|
||||||
* once.
|
* once.
|
||||||
*
|
*
|
||||||
|
* <p><b>NOTE</b>: This doesn't interact well with hierarchies of listener interfaces. If a
|
||||||
|
* listener is registered with a super-class type then it will only receive events dispatched
|
||||||
|
* directly to that super-class type. Similarly, if a listener is registered with a sub-class type
|
||||||
|
* then it will only receive events dispatched directly to that sub-class.
|
||||||
|
*
|
||||||
* @param handler A handler on the which listener events will be posted.
|
* @param handler A handler on the which listener events will be posted.
|
||||||
* @param eventListener The listener to be added.
|
* @param eventListener The listener to be added.
|
||||||
* @param listenerClass The type used to register the listener. Can be a superclass of {@code
|
* @param listenerClass The type used to register the listener. Can be a superclass of {@code
|
||||||
|
@ -18,15 +18,18 @@ package com.google.android.exoplayer2.util;
|
|||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
|
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
|
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceEventListener;
|
import com.google.android.exoplayer2.source.MediaSourceEventListener;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@ -123,6 +126,33 @@ public class MediaSourceEventDispatcherTest {
|
|||||||
verify(mediaAndDrmEventListener, never()).onDrmKeysLoaded();
|
verify(mediaAndDrmEventListener, never()).onDrmKeysLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void listenerDoesntReceiveEventsDispatchedToSubclass() {
|
||||||
|
SubclassListener subclassListener = mock(SubclassListener.class);
|
||||||
|
eventDispatcher.addEventListener(
|
||||||
|
new Handler(Looper.getMainLooper()), subclassListener, MediaSourceEventListener.class);
|
||||||
|
|
||||||
|
eventDispatcher.dispatch(SubclassListener::subclassMethod, SubclassListener.class);
|
||||||
|
|
||||||
|
// subclassListener can handle the call to subclassMethod, but it isn't called because
|
||||||
|
// it was registered 'as-a' MediaSourceEventListener, not SubclassListener.
|
||||||
|
verify(subclassListener, never()).subclassMethod(anyInt(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void listenerDoesntReceiveEventsDispatchedToSuperclass() {
|
||||||
|
SubclassListener subclassListener = mock(SubclassListener.class);
|
||||||
|
eventDispatcher.addEventListener(
|
||||||
|
new Handler(Looper.getMainLooper()), subclassListener, SubclassListener.class);
|
||||||
|
|
||||||
|
eventDispatcher.dispatch(
|
||||||
|
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
|
||||||
|
|
||||||
|
// subclassListener 'is-a' a MediaSourceEventListener, but it isn't called because the event
|
||||||
|
// is dispatched specifically to listeners registered as MediaSourceEventListener.
|
||||||
|
verify(subclassListener, never()).onMediaPeriodCreated(anyInt(), any());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void listenersAreCopiedToNewDispatcher() {
|
public void listenersAreCopiedToNewDispatcher() {
|
||||||
eventDispatcher.addEventListener(
|
eventDispatcher.addEventListener(
|
||||||
@ -185,4 +215,8 @@ public class MediaSourceEventDispatcherTest {
|
|||||||
|
|
||||||
private interface MediaAndDrmEventListener
|
private interface MediaAndDrmEventListener
|
||||||
extends MediaSourceEventListener, DrmSessionEventListener {}
|
extends MediaSourceEventListener, DrmSessionEventListener {}
|
||||||
|
|
||||||
|
private interface SubclassListener extends MediaSourceEventListener {
|
||||||
|
void subclassMethod(int windowIndex, @Nullable MediaPeriodId mediaPeriodId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user