From 2c98e8bb4f75666323477b1ccbbfb00c8054afca Mon Sep 17 00:00:00 2001 From: christosts Date: Fri, 29 Oct 2021 14:31:12 +0100 Subject: [PATCH] ExoPlayer.Builder: lazily initialize default components Initialize default components lazily in ExoPlayer.Builder to avoid redundant component instantiations, useful in cases where apps overwrite default components with ExoPlayer.Builder setters. The fields in ExoPlayer.Builder are wrapped in a Supplier (rather than just making then nullable and initializing them in ExoPlayer.Builder.build()) so that we maintain the proguarding properties of this class. PiperOrigin-RevId: 406345976 --- .../androidx/media3/exoplayer/ExoPlayer.java | 92 ++++++++++++------- .../media3/exoplayer/SimpleExoPlayer.java | 53 ++++++----- 2 files changed, 90 insertions(+), 55 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java index 9f8f9e7c7e..f2111e64f9 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java @@ -16,6 +16,7 @@ package androidx.media3.exoplayer; import static androidx.media3.common.util.Assertions.checkArgument; +import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkState; import android.content.Context; @@ -65,6 +66,7 @@ import androidx.media3.exoplayer.video.VideoFrameMetadataListener; import androidx.media3.exoplayer.video.spherical.CameraMotionListener; import androidx.media3.extractor.DefaultExtractorsFactory; import androidx.media3.extractor.ExtractorsFactory; +import com.google.common.base.Supplier; import java.util.List; /** @@ -377,12 +379,12 @@ public interface ExoPlayer extends Player { /* package */ Clock clock; /* package */ long foregroundModeTimeoutMs; - /* package */ RenderersFactory renderersFactory; - /* package */ MediaSourceFactory mediaSourceFactory; - /* package */ TrackSelector trackSelector; - /* package */ LoadControl loadControl; - /* package */ BandwidthMeter bandwidthMeter; - /* package */ AnalyticsCollector analyticsCollector; + /* package */ Supplier renderersFactorySupplier; + /* package */ Supplier mediaSourceFactorySupplier; + /* package */ Supplier trackSelectorSupplier; + /* package */ Supplier loadControlSupplier; + /* package */ Supplier bandwidthMeterSupplier; + /* package */ Supplier analyticsCollectorSupplier; /* package */ Looper looper; @Nullable /* package */ PriorityTaskManager priorityTaskManager; /* package */ AudioAttributes audioAttributes; @@ -448,8 +450,8 @@ public interface ExoPlayer extends Player { public Builder(Context context) { this( context, - new DefaultRenderersFactory(context), - new DefaultMediaSourceFactory(context, new DefaultExtractorsFactory())); + () -> new DefaultRenderersFactory(context), + () -> new DefaultMediaSourceFactory(context, new DefaultExtractorsFactory())); } /** @@ -468,8 +470,8 @@ public interface ExoPlayer extends Player { public Builder(Context context, RenderersFactory renderersFactory) { this( context, - renderersFactory, - new DefaultMediaSourceFactory(context, new DefaultExtractorsFactory())); + () -> renderersFactory, + () -> new DefaultMediaSourceFactory(context, new DefaultExtractorsFactory())); } /** @@ -487,7 +489,7 @@ public interface ExoPlayer extends Player { */ @UnstableApi public Builder(Context context, MediaSourceFactory mediaSourceFactory) { - this(context, new DefaultRenderersFactory(context), mediaSourceFactory); + this(context, () -> new DefaultRenderersFactory(context), () -> mediaSourceFactory); } /** @@ -508,14 +510,7 @@ public interface ExoPlayer extends Player { @UnstableApi public Builder( Context context, RenderersFactory renderersFactory, MediaSourceFactory mediaSourceFactory) { - this( - context, - renderersFactory, - mediaSourceFactory, - new DefaultTrackSelector(context), - new DefaultLoadControl(), - DefaultBandwidthMeter.getSingletonInstance(context), - new AnalyticsCollector(Clock.DEFAULT)); + this(context, () -> renderersFactory, () -> mediaSourceFactory); } /** @@ -542,13 +537,48 @@ public interface ExoPlayer extends Player { LoadControl loadControl, BandwidthMeter bandwidthMeter, AnalyticsCollector analyticsCollector) { + this( + context, + () -> renderersFactory, + () -> mediaSourceFactory, + () -> trackSelector, + () -> loadControl, + () -> bandwidthMeter, + () -> analyticsCollector); + } + + private Builder( + Context context, + Supplier renderersFactorySupplier, + Supplier mediaSourceFactorySupplier) { + this( + context, + renderersFactorySupplier, + mediaSourceFactorySupplier, + () -> new DefaultTrackSelector(context), + DefaultLoadControl::new, + () -> DefaultBandwidthMeter.getSingletonInstance(context), + /* analyticsCollectorSupplier= */ null); + } + + private Builder( + Context context, + Supplier renderersFactorySupplier, + Supplier mediaSourceFactorySupplier, + Supplier trackSelectorSupplier, + Supplier loadControlSupplier, + Supplier bandwidthMeterSupplier, + @Nullable Supplier analyticsCollectorSupplier) { this.context = context; - this.renderersFactory = renderersFactory; - this.mediaSourceFactory = mediaSourceFactory; - this.trackSelector = trackSelector; - this.loadControl = loadControl; - this.bandwidthMeter = bandwidthMeter; - this.analyticsCollector = analyticsCollector; + this.renderersFactorySupplier = renderersFactorySupplier; + this.mediaSourceFactorySupplier = mediaSourceFactorySupplier; + this.trackSelectorSupplier = trackSelectorSupplier; + this.loadControlSupplier = loadControlSupplier; + this.bandwidthMeterSupplier = bandwidthMeterSupplier; + this.analyticsCollectorSupplier = + analyticsCollectorSupplier != null + ? analyticsCollectorSupplier + : () -> new AnalyticsCollector(checkNotNull(clock)); looper = Util.getCurrentOrMainLooper(); audioAttributes = AudioAttributes.DEFAULT; wakeMode = C.WAKE_MODE_NONE; @@ -590,7 +620,7 @@ public interface ExoPlayer extends Player { @UnstableApi public Builder setRenderersFactory(RenderersFactory renderersFactory) { checkState(!buildCalled); - this.renderersFactory = renderersFactory; + this.renderersFactorySupplier = () -> renderersFactory; return this; } @@ -604,7 +634,7 @@ public interface ExoPlayer extends Player { @UnstableApi public Builder setMediaSourceFactory(MediaSourceFactory mediaSourceFactory) { checkState(!buildCalled); - this.mediaSourceFactory = mediaSourceFactory; + this.mediaSourceFactorySupplier = () -> mediaSourceFactory; return this; } @@ -618,7 +648,7 @@ public interface ExoPlayer extends Player { @UnstableApi public Builder setTrackSelector(TrackSelector trackSelector) { checkState(!buildCalled); - this.trackSelector = trackSelector; + this.trackSelectorSupplier = () -> trackSelector; return this; } @@ -632,7 +662,7 @@ public interface ExoPlayer extends Player { @UnstableApi public Builder setLoadControl(LoadControl loadControl) { checkState(!buildCalled); - this.loadControl = loadControl; + this.loadControlSupplier = () -> loadControl; return this; } @@ -646,7 +676,7 @@ public interface ExoPlayer extends Player { @UnstableApi public Builder setBandwidthMeter(BandwidthMeter bandwidthMeter) { checkState(!buildCalled); - this.bandwidthMeter = bandwidthMeter; + this.bandwidthMeterSupplier = () -> bandwidthMeter; return this; } @@ -675,7 +705,7 @@ public interface ExoPlayer extends Player { @UnstableApi public Builder setAnalyticsCollector(AnalyticsCollector analyticsCollector) { checkState(!buildCalled); - this.analyticsCollector = analyticsCollector; + this.analyticsCollectorSupplier = () -> analyticsCollector; return this; } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/SimpleExoPlayer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/SimpleExoPlayer.java index 9b5b0c62e5..03369c4c19 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/SimpleExoPlayer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/SimpleExoPlayer.java @@ -18,6 +18,7 @@ package androidx.media3.exoplayer; import static androidx.media3.common.C.TRACK_TYPE_AUDIO; import static androidx.media3.common.C.TRACK_TYPE_CAMERA_MOTION; import static androidx.media3.common.C.TRACK_TYPE_VIDEO; +import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.exoplayer.Renderer.MSG_SET_AUDIO_ATTRIBUTES; import static androidx.media3.exoplayer.Renderer.MSG_SET_AUDIO_SESSION_ID; import static androidx.media3.exoplayer.Renderer.MSG_SET_AUX_EFFECT_INFO; @@ -64,7 +65,6 @@ import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TracksInfo; import androidx.media3.common.VideoSize; import androidx.media3.common.text.Cue; -import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Clock; import androidx.media3.common.util.ConditionVariable; import androidx.media3.common.util.Log; @@ -420,12 +420,14 @@ public class SimpleExoPlayer extends BasePlayer Clock clock, Looper applicationLooper) { this( - new ExoPlayer.Builder(context, renderersFactory) - .setTrackSelector(trackSelector) - .setMediaSourceFactory(mediaSourceFactory) - .setLoadControl(loadControl) - .setBandwidthMeter(bandwidthMeter) - .setAnalyticsCollector(analyticsCollector) + new ExoPlayer.Builder( + context, + renderersFactory, + mediaSourceFactory, + trackSelector, + loadControl, + bandwidthMeter, + analyticsCollector) .setUseLazyPreparation(useLazyPreparation) .setClock(clock) .setLooper(applicationLooper)); @@ -442,7 +444,7 @@ public class SimpleExoPlayer extends BasePlayer constructorFinished = new ConditionVariable(); try { applicationContext = builder.context.getApplicationContext(); - analyticsCollector = builder.analyticsCollector; + analyticsCollector = builder.analyticsCollectorSupplier.get(); priorityTaskManager = builder.priorityTaskManager; audioAttributes = builder.audioAttributes; videoScalingMode = builder.videoScalingMode; @@ -454,12 +456,15 @@ public class SimpleExoPlayer extends BasePlayer listeners = new CopyOnWriteArraySet<>(); Handler eventHandler = new Handler(builder.looper); renderers = - builder.renderersFactory.createRenderers( - eventHandler, - componentListener, - componentListener, - componentListener, - componentListener); + builder + .renderersFactorySupplier + .get() + .createRenderers( + eventHandler, + componentListener, + componentListener, + componentListener, + componentListener); // Set initial values. volume = 1; @@ -487,10 +492,10 @@ public class SimpleExoPlayer extends BasePlayer player = new ExoPlayerImpl( renderers, - builder.trackSelector, - builder.mediaSourceFactory, - builder.loadControl, - builder.bandwidthMeter, + builder.trackSelectorSupplier.get(), + builder.mediaSourceFactorySupplier.get(), + builder.loadControlSupplier.get(), + builder.bandwidthMeterSupplier.get(), analyticsCollector, builder.useLazyPreparation, builder.seekParameters, @@ -859,7 +864,7 @@ public class SimpleExoPlayer extends BasePlayer @Override public void addAnalyticsListener(AnalyticsListener listener) { // Don't verify application thread. We allow calls to this method from any thread. - Assertions.checkNotNull(listener); + checkNotNull(listener); analyticsCollector.addListener(listener); } @@ -885,7 +890,7 @@ public class SimpleExoPlayer extends BasePlayer return; } if (isPriorityTaskManagerRegistered) { - Assertions.checkNotNull(this.priorityTaskManager).remove(C.PRIORITY_PLAYBACK); + checkNotNull(this.priorityTaskManager).remove(C.PRIORITY_PLAYBACK); } if (priorityTaskManager != null && isLoading()) { priorityTaskManager.add(C.PRIORITY_PLAYBACK); @@ -993,7 +998,7 @@ public class SimpleExoPlayer extends BasePlayer @Override public void addListener(Listener listener) { - Assertions.checkNotNull(listener); + checkNotNull(listener); listeners.add(listener); EventListener eventListener = listener; addListener(eventListener); @@ -1003,13 +1008,13 @@ public class SimpleExoPlayer extends BasePlayer @Override public void addListener(Player.EventListener listener) { // Don't verify application thread. We allow calls to this method from any thread. - Assertions.checkNotNull(listener); + checkNotNull(listener); player.addEventListener(listener); } @Override public void removeListener(Listener listener) { - Assertions.checkNotNull(listener); + checkNotNull(listener); listeners.remove(listener); EventListener eventListener = listener; removeListener(eventListener); @@ -1333,7 +1338,7 @@ public class SimpleExoPlayer extends BasePlayer ownedSurface = null; } if (isPriorityTaskManagerRegistered) { - Assertions.checkNotNull(priorityTaskManager).remove(C.PRIORITY_PLAYBACK); + checkNotNull(priorityTaskManager).remove(C.PRIORITY_PLAYBACK); isPriorityTaskManagerRegistered = false; } currentCues = Collections.emptyList();