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
This commit is contained in:
christosts 2021-10-29 14:31:12 +01:00 committed by Ian Baker
parent 9d5fd4f402
commit 2c98e8bb4f
2 changed files with 90 additions and 55 deletions

View File

@ -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<RenderersFactory> renderersFactorySupplier;
/* package */ Supplier<MediaSourceFactory> mediaSourceFactorySupplier;
/* package */ Supplier<TrackSelector> trackSelectorSupplier;
/* package */ Supplier<LoadControl> loadControlSupplier;
/* package */ Supplier<BandwidthMeter> bandwidthMeterSupplier;
/* package */ Supplier<AnalyticsCollector> 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<RenderersFactory> renderersFactorySupplier,
Supplier<MediaSourceFactory> mediaSourceFactorySupplier) {
this(
context,
renderersFactorySupplier,
mediaSourceFactorySupplier,
() -> new DefaultTrackSelector(context),
DefaultLoadControl::new,
() -> DefaultBandwidthMeter.getSingletonInstance(context),
/* analyticsCollectorSupplier= */ null);
}
private Builder(
Context context,
Supplier<RenderersFactory> renderersFactorySupplier,
Supplier<MediaSourceFactory> mediaSourceFactorySupplier,
Supplier<TrackSelector> trackSelectorSupplier,
Supplier<LoadControl> loadControlSupplier,
Supplier<BandwidthMeter> bandwidthMeterSupplier,
@Nullable Supplier<AnalyticsCollector> 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;
}

View File

@ -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();