如何使用协程在while中动态等待时间

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

我封装了一段等待8个小时才结束。我需要重复里面的任务,直到时间达到8小时。如何在开始下一个周期之前等待任务结束,而不是固定的延迟时间?

fun startPeriodicTask(timeout: Long, block: suspend CoroutineScope.() -> Unit) {
         periodicTask = viewModelScope.launcher {
            while (dataService.timeConfigData.runTime.value!!.toLong() < dataService.timeConfigData.timeEnd.value!!.toLong()) {
                withTimeout(timeout) {
                    // 执行任务
                    XLog.v("startPeriodicTask run block")
                    block()
                }
                delay(timeout)
            }
        }
    }
    vm.startPeriodicTask(2000) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    mVibrator?.vibrate(VibrationEffect.createOneShot(1000, 255))
    } else {
    mVibrator?.vibrate(longArrayOf(1000, 2000), 1)
    }
    }

我的理解是,这是不可行的,因为协程是一个递归过程,所以当我挂起它的时候,我就等不及了,主线程就被阻塞了。

====================================================== ===============

我是按照broot的方法修改的。其实我并没有等,只是启动了协程任务,导致while在短时间内被重复了无数次。不知道我的修改是否正确。

fun startPeriodicTask(timeout: Long, block:() -> Unit) {
//        periodicTask = viewModelScope.launcher {
    while (dataService.timeConfigData.runTime.value!!.toLong() < 
    dataService.timeConfigData.timeEnd.value!!.toLong()) {
        XLog.v("startPeriodicTask run block")
        block()
//                delay(timeout)
//            }
    }
}

        

vm.dataService.
testConfigData.isSpeakerSwitch.observe(viewLifecycleOwner) {
        if (it) {
            vm.startPeriodicTask(25000) {
                play {
                    XLog.d("play end")
                }
            }
        }
    }

    fun play(onCompleted: () -> Unit) {
    stop()
    mMediaPlayer = MediaPlayer.create(requireContext(), R.raw.testsignal)
    mMediaPlayer?.setOnCompletionListener(OnCompletionListener {
        stop()
        onCompleted()
    })
    mMediaPlayer?.start()
}

enter image description here

android while-loop jetpack
1个回答
0
投票

我又解决了这个问题。我用协程在块中等待来解决。感谢@broot

    fun startPeriodicTask(timeout: Long, block:suspend CoroutineScope.() -> Unit) {
     periodicTask = viewModelScope.launcher {
        while (dataService.timeConfigData.runTime.value!!.toLong() < dataService.timeConfigData.timeEnd.value!!.toLong()) {
                // 执行任务
                XLog.v("startPeriodicTask run block")
                block()
        }
    }
}


vm.dataService.testConfigData.isSpeakerSwitch.observe(viewLifecycleOwner) {
        if (it) {
            vm.startPeriodicTask(25000) {
                    play {
                        XLog.d("play end")
                    }
            }
        }
    }

    suspend fun play(onCompleted: () -> Unit): Boolean {
    return suspendCancellableCoroutine { suspend ->
        stop()
        mMediaPlayer = MediaPlayer.create(requireContext(), R.raw.testsignal)
        mMediaPlayer?.setOnCompletionListener(OnCompletionListener {
            stop()
            onCompleted()
            suspend.resume(true) {
                XLog.d("play end")
            }
        })
        mMediaPlayer?.start()
    }

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