ExoPlayer播放器剖析(三)流程分析---从build到prepare看ExoPlayer的创建流程

本文深入剖析ExoPlayer播放器的创建流程,从SimpleExoPlayer实例化开始,逐步介绍内部组件如ExoPlayerImplInternal的实现细节,以及关键方法如prepare和setPlayWhenReady的执行过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关联博客:

ExoPlayer播放器剖析(一)进入ExoPlayer的世界
ExoPlayer播放器剖析(二)编写exoplayer的demo
ExoPlayer播放器剖析(三)流程分析—从build到prepare看ExoPlayer的创建流程
ExoPlayer播放器剖析(四)从renderer.render函数分析至MediaCodec
ExoPlayer播放器剖析(五)ExoPlayer对AudioTrack的操作
ExoPlayer播放器剖析(六)ExoPlayer同步机制分析
ExoPlayer播放器剖析(七)ExoPlayer对音频时间戳的处理
ExoPlayer播放器扩展(一)DASH流与HLS流简介

一、前言:
上一篇博客介绍了exoplayer的简单demo,对流程有了一个大致的了解,我们都知道exoplayer的本质是调用Android原生的MediaCodec接口,这篇博客将着重分析其内部实现逻辑,看exoplayer是如何完成创建的。

二、流程分析:
先贴出上篇博客中讲exoplayer初始化的五步曲:

    private fun initPlayer(playUri: String?) {
   

        if (playUri == null){
   
            Log.d("ExoTest", "playUri is null!")
            return
        }

        /* 1.创建SimpleExoPlayer实例 */
        mPlayer = SimpleExoPlayer.Builder(this).build()

        /* 2.创建播放菜单并添加到播放器 */
        val firstLocalMediaItem = MediaItem.fromUri(playUri)
        mPlayer!!.addMediaItem(firstLocalMediaItem)

        /* 3.设置播放方式为自动播放 */
        mPlayer!!.playWhenReady = true

        /* 4.将SimpleExoPlayer实例设置到StyledPlayerView中 */
        mPlayerView!!.player = mPlayer

        /* 5,设置播放器状态为prepare */
        mPlayer!!.prepare()
    }

实际上,我们可以看到,真正跟播放器相关的只有1、3和5三步,我们就从这三步入手看看exoplayer内部到底是如何实现的。

1.分析SimpleExoPlayer.Builder(this).build():
看build实现如下:

    /**
     * Builds a {@link SimpleExoPlayer} instance.
     *
     * @throws IllegalStateException If this method has already been called.
     */
    public SimpleExoPlayer build() {
   
      Assertions.checkState(!buildCalled);
      buildCalled = true;
      return new SimpleExoPlayer(/* builder= */ this);
    }
  }

看build方式实际上是实例了一个SimpleExoPlayer对象,继续跟进到SimpleExoPlayer的构造函数:

  protected SimpleExoPlayer(Builder builder) {
   
  	...
  		/* 构建render */
  	    renderers =
        builder.renderersFactory.createRenderers(
            eventHandler,
            componentListener,
            componentListener,
            componentListener,
            componentListener);
  	...	  
    // Build the player and associated objects.
    player =
        new ExoPlayerImpl(
            renderers,
            builder.trackSelector,
            builder.mediaSourceFactory,
            builder.loadControl,
            builder.bandwidthMeter,
            analyticsCollector,
            builder.useLazyPreparation,
            builder.seekParameters,
            builder.pauseAtEndOfMediaItems,
            builder.clock,
            builder.looper);
    player.addListener(componentListener);
    videoDebugListeners.add(analyticsCollector);
    videoListeners.add(analyticsCollector);
    audioDebugListeners.add(analyticsCollector);
    audioListeners.add(analyticsCollector);
    addMetadataOutput(analyticsCollector);
    	...
  }

可以看到,SimpleExoPlayer的构造里面继续去实例化了一个ExoPlayerImpl的对象,再往下跟进:

  public ExoPlayerImpl(
      Renderer[] renderers,
      TrackSelector trackSelector,
      MediaSourceFactory mediaSourceFactory,
      LoadControl loadControl,
      BandwidthMeter bandwidthMeter,
      @Nullable AnalyticsCollector analyticsCollector,
      boolean useLazyPreparation,
      SeekParameters seekParameters,
      boolean pauseAtEndOfMediaItems,
      Clock clock,
      Looper applicationLooper) {
   
	...
	    internalPlayer =
        new ExoPlayerImplInternal(
            renderers,
            trackSelector,
            emptyTrackSelectorResult,
            loadControl,
            bandwidthMeter,
            repeatMode,
            shuffleModeEnabled,
            analyticsCollector,
            seekParameters,
            pauseAtEndOfMediaItems,
            applicationLooper,
            clock,
            playbackInfoUpdateListener);
    internalPlayerHandler = new Handler(internalPlayer.
### MediaPlayer与ExoPlayer的区别及适用场景 #### 性能对比 `MediaPlayer` 是 Android 平台上较早提供的多媒体播放框架之一,适用于简单的音频和视频播放需求。然而,它存在一些局限性,例如缺乏灵活性和支持的格式有限[^1]。相比之下,`ExoPlayer` 是 Google 推出的一个功能更强大的开源媒体播放器库,支持自定义扩展以及多种流媒体协议(如 DASH 和 HLS),并提供了更高的性能和稳定性。 #### 功能特性差异 以下是两者的主要功能区别: - **可定制化程度**: `ExoPlayer` 提供了高度灵活的 API 设计,允许开发者轻松实现复杂的用例,比如多音轨切换、字幕同步等功能;而 `MediaPlayer` 的接口较为固定,难以满足复杂的应用需求。 - **支持的媒体格式**: `ExoPlayer` 支持广泛的文件类型和网络传输标准,包括但不限于 MP4、MKV、WebM 等常见容器格式及其内部编码方式,还特别优化处理了基于 HTTP 的动态适应比特率流服务[DASH](https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP)[^2] 。与此同时,尽管 `MediaPlayer` 能够覆盖大部分基础性的解码工作,但对于某些特定平台或者新兴技术的支持则显得力不从心。 - **错误恢复机制**: 当遇到不可预见的情况时(例如网络中断),`ExoPlayer` 可通过内置策略自动尝试重新连接资源直至成功加载为止;相反地,在相同条件下,传统意义上的 `MediaPlayer` 往往会直接抛出异常终止操作流程[^3]。 #### 使用案例分析 对于只需要简单回放本地存储介质上的静态内容的小型项目来说,继续沿用现有的 `MediaPlayer` 解决方案可能是最经济实惠的选择。但是,如果目标应用程序涉及到在线直播、点播服务或者是跨设备间无缝衔接体验,则推荐采用更加先进且全面的 `ExoPlayer` 来构建核心逻辑部分。 ```java // Example of using ExoPlayer in Java code snippet. SimpleExoPlayer player; DefaultTrackSelector trackSelector; trackSelector = new DefaultTrackSelector(); player = new SimpleExoPlayer.Builder(context).build(); MediaItem mediaItem = MediaItem.fromUri("https://example.com/sample.mp4"); player.setMediaItem(mediaItem); player.prepare(); player.play(); ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值