gpt4 book ai didi

android - 在Fragment中处理Coroutine的正确方法

转载 作者:行者123 更新时间:2023-12-03 08:46:37 25 4
gpt4 key购买 nike

以下挂起函数会在 1 秒延迟内更新进度条和 2 个 TextView。进度条指示 MP3 的进度,TextView 分别指示已用时间和剩余时间。

用户可以离开 fragment 并再次返回,这意味着 fragment ( View )被销毁并再次创建。

我想知道这个实现是否正确和/或是否有更好的实现和/或替代方案(第一次实现协程)。这是一些代码:

class BookViewFragment : Fragment(), CoroutineScope {
private var _binding: FragmentBookViewerBinding? = null
private val bookViewFragmentBinding get() = _binding!!

private lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentBookViewerBinding.inflate(layoutInflater)
val view = bookViewFragmentBinding.root
job = Job()
initMediaPlayer()
return view
}

override fun onDestroyView() {
super.onDestroyView()
job.cancel()
_binding = null
mp.stop()
mp.release()
}

private fun initMediaPlayer() {
mp = MediaPlayer()

mp.run {
setDataSource(...)
setVolume(0.5f, 0.5f)
prepare()
}
totalTime = mp.duration
initPositionBar()
}

private fun initPositionBar() {
bookViewFragmentBinding.mediaPosition.max = totalTime

launch {
setTimeOnProgressBar()
}
}

private suspend fun setTimeOnProgressBar() {
coroutineScope {
launch {
var progress = mp.currentPosition
while (progress < mp.duration) {
progress = mp.currentPosition
bookViewFragmentBinding.mediaPosition.progress = progress
val timePlayed = progress
val timeLeft = mp.duration - timePlayed
bookViewFragmentBinding.timePlayed.text = formatIntToTime(timePlayed)
bookViewFragmentBinding.timeLeft.text =
getString(R.string.time_left, formatIntToTime(timeLeft))
delay(1000)
}
}
}
}
}

最佳答案

这看起来是正确的,但是您在循环周围创建了两个不必要的协程层。在 setTimeOnProgressBar() 中,您已将协程包装在一个新的 coroutineScope 中,但您不将其用于任何用途。可以将其删除,然后这根本就不必是挂起函数。因此,您还可以删除在 initPositionBar() 中包装对 setTimeOnProgressBar() 的调用的协程。

此外,您还重新创建了 Android ktx 库已提供的一堆样板。已经有一个 lifecycleScope 扩展属性可用于启动协程,并且它会在 onDestroyView() 中自动取消。因此,您不需要创建父作业或覆盖 coroutineContext,或取消父作业。

启动协程时可以使用lifecycleScope.launch

class BookViewFragment : Fragment() {
private var _binding: FragmentBookViewerBinding? = null
private val bookViewFragmentBinding get() = _binding!!

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentBookViewerBinding.inflate(layoutInflater)
val view = bookViewFragmentBinding.root
initMediaPlayer()
return view
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
mp.stop()
mp.release()
}

private fun initMediaPlayer() {
mp = MediaPlayer()

mp.run {
setDataSource(...)
setVolume(0.5f, 0.5f)
prepare()
}
totalTime = mp.duration
initPositionBar()
}

private fun initPositionBar() {
bookViewFragmentBinding.mediaPosition.max = totalTime

setTimeOnProgressBar()
}

private fun setTimeOnProgressBar() {
lifecycleScope.launch {
var progress = mp.currentPosition
while (progress < mp.duration) {
progress = mp.currentPosition
bookViewFragmentBinding.mediaPosition.progress = progress
val timePlayed = progress
val timeLeft = mp.duration - timePlayed
bookViewFragmentBinding.timePlayed.text = formatIntToTime(timePlayed)
bookViewFragmentBinding.timeLeft.text =
getString(R.string.time_left, formatIntToTime(timeLeft))
delay(1000)
}
}
}
}

关于android - 在Fragment中处理Coroutine的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61229337/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com