添加 onPlayerStateChanged 侦听器时,ExoPlayer 重播按钮会中断,这会导致 Jetpack Compose 中的重组

问题描述 投票:0回答:1

我已经创建了一个 ExoPlayer 实例和一个按钮,供用户在想要重播视频时按下。该按钮仅在视频播放期间有效;当视频完成播放时,按钮不再起作用。当视频完成播放时,我有代码运行以显示一个按钮,我认为这是破坏此重播按钮的原因,但我不知道为什么!

这与我在发布的另一个问题中遇到的问题相同,但我对导致该问题的原因有一些想法,因此发布了另一篇文章。

我在

onCreate()
方法中运行下面的代码,以确保代码在Activity启动时只运行一次:

val context = LocalContext.current

val exoPlayer = ExoPlayer.Builder(LocalContext.current)
        .build()
        .also { exoPlayer ->
            val mediaItem = MediaItem.Builder()
                    .setUri(Uri.parse("android.resource://" + packageName + "/" + R.raw.xxxxxx))
                    .build()
            exoPlayer.setMediaItem(mediaItem)
            exoPlayer.playWhenReady = true
            exoPlayer.videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
            exoPlayer.addListener(playerEventListener)
            exoPlayer.prepare()
        }

DisposableEffect(
        AndroidView(factory = {
            StyledPlayerView(context).apply {
                hideController()
                useController = false
                player = exoPlayer
            }
    })) {
    onDispose { exoPlayer.release() }
}

然后是创建重播按钮的代码。这也是在

onCreate()
方法中运行。

Button(onClick = {                             
    exoPlayer.seekTo(0)
    exoPlayer.play() 
    },){
    Text(
       text = "replay",
       fontSize = 18.sp,
       modifier = Modifier.padding(5.dp),
       textAlign = TextAlign.Center)
}

现在这段代码在播放过程中有效,但是当视频结束时按钮不再起作用,我只能看到视频的最后一帧。

我发现这可能与我

exoPlayer.addListener(playerEventListener)
行中的方法中的 viewModel 方法有关:

    private val playerEventListener = object : Player.Listener
    {
        override fun onPlaybackStateChanged(playbackState: Int)
        {
            super.onPlaybackStateChanged(playbackState)
            // when the video ends, make the button to move onto the next page appear
            if (playbackState==ExoPlayer.STATE_ENDED)
            {
                viewModel.showNextButton()
            }
        }
    }

下面是 viewModel 的代码,以便您可以看到

viewModel.showNextButton()
方法:

data class TutorialUiState(
        val showNextButton: MutableState<Boolean> = mutableStateOf(false)
                          )

class TutorialViewModel(application: HDiagsApplication) : AndroidViewModel(application)
{
    private val _uiState = MutableStateFlow(TutorialUiState())
    val uiState = _uiState.asStateFlow()

    fun showNextButton()
    {
        uiState.value.showNextButton.value = true
    }
}

uiState.value.showNextButton.value
设置为true时,UI上会显示另一个按钮,这是按钮的代码:


val uiState by remember {
    mutableStateOf(viewModel.uiState.value)
}

if (viewModel.showButton.value)
{
   ButtonCore(text = "Begin test") {
       startActivity(Intent(this@TutorialJetpack, ParadigmControllerJetpack::class.java))
   }
}

我目前的工作理论是

viewModel.showNextButton()
方法中的这个值变化会导致破坏 exoplayer 的重组,但是我如何在视频结束时显示一个新按钮而不导致这个问题?

android android-jetpack-compose exoplayer exoplayer2.x
1个回答
0
投票

问题是我忘了使用

remember
。这意味着每次发生重组时都会创建一个新玩家。

在我的代码中:

val exoPlayer = ExoPlayer
    .Builder(context)
    .build()
    .also { exoPlayer ->
    val mediaItem = MediaItem.Builder()
}

应该换成...

val exoPlayer = remember {
    ExoPlayer.Builder(context)
        .build()
        .also { exoPlayer ->
          val mediaItem = MediaItem.Builder()
         }

这样就不会发生了!

这解决了我的问题,我希望它也能帮助那里的人 :)

© www.soinside.com 2019 - 2024. All rights reserved.