Android 运行函数,直到用户单击按钮
我正在尝试开发一个包含节拍器的应用程序,以用户指定的间隔重复音调。我可以让节拍器播放-这是由onClick事件触发的,但应用程序在我创建的Android 运行函数,直到用户单击按钮,android,kotlin,Android,Kotlin,我正在尝试开发一个包含节拍器的应用程序,以用户指定的间隔重复音调。我可以让节拍器播放-这是由onClick事件触发的,但应用程序在我创建的startMetronome()函数中被锁定。我知道这是为什么,我只是尽量确保我能够播放音调,并在用户定义的时间间隔重复: private fun startMetronome(interval: Long) { while (true) { soundPool?.play(soundId, 1F, 1F, 0, 0,
startMetronome()
函数中被锁定。我知道这是为什么,我只是尽量确保我能够播放音调,并在用户定义的时间间隔重复:
private fun startMetronome(interval: Long) {
while (true) {
soundPool?.play(soundId, 1F, 1F, 0, 0, 1F)
Thread.sleep(interval)
}
}
显然,这永远不会离开
startMetronome()
函数并锁定应用程序(我也希望如此)。我只是不知道如何触发此功能,然后允许应用程序按钮仍处于活动状态,允许触发“中断”,然后以调整的间隔启动此功能。您需要在另一个线程上启动声音,以便它不会阻塞UI线程,实现这一点的最基本方法是通过异步任务
伪代码:
private class playSoundTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Integer... interval) {
if (!isCancelled()){
//start playing the sound
} else{
//stop playing the sound
}
}
protected void onProgressUpdate(Void... progress) {
}
protected void onPostExecute(Void result) {
}
}
私有类playSoundTask扩展了AsyncTask{
受保护的Void doInBackground(整数…间隔){
如果(!isCancelled()){
//开始播放声音
}否则{
//停止播放声音
}
}
受保护的void onProgressUpdate(void…progress){
}
受保护的void onPostExecute(void结果){
}
}
启动任务调用playSoundTask().execute()代码>
停止任务调用playSoundTask().cancel()代码>您需要在另一个线程上启动声音,这样它就不会阻塞UI线程,最基本的方法是通过异步任务
伪代码:
private class playSoundTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Integer... interval) {
if (!isCancelled()){
//start playing the sound
} else{
//stop playing the sound
}
}
protected void onProgressUpdate(Void... progress) {
}
protected void onPostExecute(Void result) {
}
}
私有类playSoundTask扩展了AsyncTask{
受保护的Void doInBackground(整数…间隔){
如果(!isCancelled()){
//开始播放声音
}否则{
//停止播放声音
}
}
受保护的void onProgressUpdate(void…progress){
}
受保护的void onPostExecute(void结果){
}
}
启动任务调用playSoundTask().execute()代码>
停止任务调用playSoundTask().cancel()代码>您可以使用这样的协同程序来实现这一点。我不知道时间会有多准确
private var metronomeJob: Job? = null
private fun startMetronome(interval: Long) {
metronomeJob?.cancel()
metronomeJob = lifecycleScope.launch(Dispatchers.IO) {
while (isActive) {
soundPool?.play(soundId, 1F, 1F, 0, 0, 1F)
delay(interval)
}
}
}
private fun stopMetronome() {
metronomeJob?.cancel()
metronomeJob = null
}
您可以通过这样的协同程序来实现这一点。我不知道时间会有多准确
private var metronomeJob: Job? = null
private fun startMetronome(interval: Long) {
metronomeJob?.cancel()
metronomeJob = lifecycleScope.launch(Dispatchers.IO) {
while (isActive) {
soundPool?.play(soundId, 1F, 1F, 0, 0, 1F)
delay(interval)
}
}
}
private fun stopMetronome() {
metronomeJob?.cancel()
metronomeJob = null
}
首先,为什么要使用线程.sleep()
?如果阻塞线程只会浪费资源,请使用诸如delay()
之类的协程函数或任何其他不阻塞线程的异步方法。我只是使用我想到的第一件事来测试“延迟”,以确认实际的声音以正确的间隔播放。但是谢谢你提供的信息。你为什么要首先使用线程.sleep()
?如果阻塞线程只会浪费资源,请使用诸如delay()
之类的协程函数或任何其他不阻塞线程的异步方法。我只是使用我想到的第一件事来测试“延迟”,以确认实际的声音以正确的间隔播放。但是谢谢你提供的信息,谢谢。这通常是可行的,但当间隔小于1秒(间隔=1000)时,会出现大量失真和剪切。很难说是音频文件本身还是什么,因为音频变得如此混乱。基本上,我的测试是30bpm(精细)、60bpm(精细)、61bpm(出现问题)。猜猜是什么原因造成的吗?对不起,没有。我对音频播放没有太多的研究。谢谢。这通常是可行的,但当间隔小于1秒(间隔=1000)时,会出现大量失真和剪切。很难说是音频文件本身还是什么,因为音频变得如此混乱。基本上,我的测试是30bpm(精细)、60bpm(精细)、61bpm(出现问题)。猜猜是什么原因造成的?对不起,没有。我对音频播放没有太多研究。