Home > Mobile >  How to kill a coroutine in Kotlin?
How to kill a coroutine in Kotlin?

Time:10-21

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:)

  • Related