I,m want to create a metronome app with Kotlin for Android. I,m starting coroutine for click playback:
playBtn.setOnClickListener {
if (!isPlaying) {
playBtn.setText(R.string.stop)
isPlaying = true
}
else {
isPlaying = false
playBtn.setText(R.string.play)
}
if (isPlaying) {
GlobalScope.launch {
while (isPlaying) {
delay(bpmToMillis)
launch { metro1.start() }
}
}
}
}
It works fine, but if you rapidly taping "play" button, it starts another thread with metronome sound. So, instead of one "click" it plays two or three with little delay.
I tried to move code blocks and using sleep and TimeUnit, but it doesnt work.
I,m noob, no hate pls:)
CodePudding user response:
playBtn.setOnClickListener {
if (!isPlaying) {
playBtn.setText(R.string.stop)
isPlaying = true
}
else {
isPlaying = false
playBtn.setText(R.string.play)
}
if (isPlaying) {
// assigned coroutine scope to variable
var job = GlobalScope.launch {
while (isPlaying) {
if(isActive){
delay(bpmToMillis)
launch { metro1.start() }
}
}
//some condition to cancel the coroutine
job.cancel()
}
}
}
CodePudding user response:
Thanks for help, everyone! You pushed me in right direction.
Only way playback is not bugged if I adding new var with null or empty coroutine:
var job: Job? = null
// or
var job: Job = GlobalScope.launch {}
and then assign value within the if-statement:
playBtn.setOnClickListener {
if (!isPlaying) {
playBtn.setText(R.string.stop)
isPlaying = true
}
else {
isPlaying = false
playBtn.setText(R.string.play)
//job cancel here
job?.cancel()
}
if (isPlaying) {
//var assigment here
job = GlobalScope.launch {
while (isPlaying) {
metro1.start()
delay(bpmToMillis)
}
}
}
}
Otherwise job is not visible frome upper levels and you cant REALLY cancel it when you need to, i think:)