如何将延迟处理程序与实时匹配?

how to match postdelayed handler with real time?

我设置进度条最大值=30000,延迟时间100毫秒,播放30秒。所以当我尝试时,我得到的最终时间超过 30 秒。当我将延迟时间设置为1000ms时,结果是正确的。但是当我将时间设置为 100 毫秒时,我得到了 34~35 秒,超过了我想要的 30 秒。使用延迟时间100ms时如何精确到30秒?

    private val delayChangeProgress = 100L

        binding.recordStartButton.setOnClickListener {
            onRecord(true)
            binding.recordStartButton.visibility = View.GONE
            binding.recordStopButton.visibility = View.VISIBLE
            recordChangeHandler.postDelayed(updateRecordProgressTask,delayChangeProgress)
            showLog("onChangeRecordPregressBar StartTime: "+ getRecordDateFormat(mContext).format(Date(System.currentTimeMillis())))
        }

    private val updateRecordProgressTask: Runnable = object : Runnable {
        override fun run() {
            if(recorder!=null) {
                onChangeRecordPregressBar()
                recordChangeHandler.postDelayed(this, delayChangeProgress)
            }
        }
    }

    private fun onChangeRecordPregressBar(){
        binding.audioStartProgressBar.max = 30000
        showLog("onChangeRecordPregressBar : "+binding.audioStartProgressBar.progress)
        binding.audioStartProgressBar.progress += delayChangeProgress.toInt()
        if(binding.audioStartProgressBar.max == binding.audioStartProgressBar.progress){
            stopRecording()
            binding.audioStartProgressBar.progress=0
            recordChangeHandler.removeCallbacks(updateRecordProgressTask)
            showLog("onChangeRecordPregressBar EndTime: "+ getRecordDateFormat(mContext).format(Date(System.currentTimeMillis())))
        }
    }

使用1000ms延时时的log

onChangeRecordPregressBar StartTime: 46:09
D/TAG: onChangeRecordPregressBar : 0
D/TAG: onChangeRecordPregressBar : 1000
...
D/TAG: onChangeRecordPregressBar : 28000
D/TAG: onChangeRecordPregressBar : 29000
D/TAG: onChangeRecordPregressBar EndTime: 46:39

使用100ms延时时的log

onChangeRecordPregressBar StartTime: 51:55
D/TAG: onChangeRecordPregressBar : 0
D/TAG: onChangeRecordPregressBar : 100
D/TAG: onChangeRecordPregressBar : 200
...
D/TAG: onChangeRecordPregressBar : 29800
D/TAG: onChangeRecordPregressBar : 29900
D/TAG: onChangeRecordPregressBar EndTime: 52:28

实际上,您不应该依赖投入 postDelayed 的时间来更新进度。它不会执行您设置的完全相同的 100 或 1000 毫秒。当您初始化 Handler 时,您的 Handler 使用与 MainThread 相同的 MessageQueue,因此这取决于有多少任务或消息,因此您已经设置的时间可以增加。

您应该使用变量来节省时间来记录开始示例 startTime 并且当您调用时 onChangeRecordPregressBar 您应该计算持续时间。试试这个

private val delayChangeProgress = 100L
private var startTime = 0L

        binding.recordStartButton.setOnClickListener {
            startTime = System.currentTimeMillis()
            onRecord(true)
            binding.recordStartButton.visibility = View.GONE
            binding.recordStopButton.visibility = View.VISIBLE
            recordChangeHandler.postDelayed(updateRecordProgressTask,delayChangeProgress)
            showLog("onChangeRecordPregressBar StartTime: "+ getRecordDateFormat(mContext).format(Date(System.currentTimeMillis())))
        }

    private val updateRecordProgressTask: Runnable = object : Runnable {
        override fun run() {
            if(recorder!=null) {
                onChangeRecordPregressBar()
                recordChangeHandler.postDelayed(this, delayChangeProgress)
            }
        }
    }

    private fun onChangeRecordPregressBar(){
        binding.audioStartProgressBar.max = 30000
        showLog("onChangeRecordPregressBar : "+binding.audioStartProgressBar.progress)
        binding.audioStartProgressBar.progress = System.currentTimeMillis() - startTime
        if(binding.audioStartProgressBar.max == binding.audioStartProgressBar.progress){
            stopRecording()
            binding.audioStartProgressBar.progress=0
            recordChangeHandler.removeCallbacks(updateRecordProgressTask)
            showLog("onChangeRecordPregressBar EndTime: "+ getRecordDateFormat(mContext).format(Date(System.currentTimeMillis())))
        }
    }