返回

如何在 Android 上将 ExoPlayer 运行在后台线程,解决 UI 冻结问题?

Android

如何在 Android 上将 ExoPlayer 运行在后台线程

问题:UI 冻结和无法在后台线程上使用 androidx.media3.ui.PlayerView

在使用 Jetpack Compose 和 ExoPlayer 播放视频时,导航到播放屏幕时 UI 可能会冻结。这是因为在准备和初始化 ExoPlayer 时会进行大量的工作,导致主线程上的帧丢失。此外, androidx.media3.ui.PlayerView 无法在后台线程上使用,这使得无法解决 UI 冻结问题。

解决方案:自定义视频播放器视图

为了解决这些问题,我们需要创建一个自定义视频播放器视图,该视图可以在后台线程上运行 ExoPlayer,并将渲染委托给主线程上的 SurfaceView。

自定义视频播放器视图

class CustomVideoView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    // ...

    // 在后台线程上准备 ExoPlayer
    fun prepareExoPlayer(mediaItem: MediaItem) {
        // ...
    }

    // ...

}

在 Compose 中使用自定义视图

// ...

// 在后台线程上准备 ExoPlayer
LaunchedEffect(mediaItem) {
    customVideoView.prepareExoPlayer(mediaItem)
}

// ...

结论

通过使用自定义视频播放器视图,我们可以将 ExoPlayer 的工作移动到后台线程,从而消除 UI 冻结问题。我们还可以使用 SurfaceView 在主线程上渲染视频,保持流畅的播放体验。

常见问题解答

  1. 为什么使用 HandlerThread?
    HandlerThread 提供了一个单独的 Looper,允许我们独立于主线程执行任务。
  2. 如何释放 ExoPlayer?
    在视图销毁时调用 customVideoView.releaseExoPlayer()
  3. 自定义视频播放器视图有什么优势?
    它允许我们在后台线程上处理 ExoPlayer 任务,从而防止 UI 冻结。
  4. 是否可以使用 androidx.media3.ui.PlayerView 来实现同样的功能?
    不可以,androidx.media3.ui.PlayerView 无法在后台线程上使用。
  5. 这种方法是否适用于所有 Android 版本?
    是的,这种方法适用于所有支持 ExoPlayer 的 Android 版本。