我已经创建了一个 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 的重组,但是我如何在视频结束时显示一个新按钮而不导致这个问题?
问题是我忘了使用
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()
}
这样就不会发生了!
这解决了我的问题,我希望它也能帮助那里的人 :)