Mc-Ac
Mc-Ac

Reputation: 161

Kotlin Handler class: How to stop a thread - from inside of run() - when a condition is met?

I am currently learning how to develop android applications. For my first app, I wanted to build a simple clicker with a primitive combat sistem.

In my code, I have created a Handler instance and a Runnable object. Inside of this "delayed loop" the enemy attacks the player instance every 3 seconds, dealing damage. Inside the loop I also test when the player's hp is less or equals 0; when the condition is met I want to stop the runnable object.

How do i do this? I tried calling a function stopCombat() which contains Handler.removeCallbacks, but i can't call a function before declaration. I tried putting .removeCallbacks(this) inside run(), but it also doesn't work.

val mainHandler = Handler(Looper.getMainLooper())

    fun playerDied() {
        ongoingFight = false
        combatLog.append("${myPlayer.name} has been defeated!\n")
        myPlayer.currentHitPoints = myPlayer.maxHitPoints / 2
        myPlayer.gold = 0
        gold.text = "${myPlayer.gold} gold"
    }


    val performTask = object : Runnable {
        override fun run() {
            val enemyHit = enemyAttack(myPlayer, myEnemy)
            // Call a function to stop this thread if the condition is met:
            if (myPlayer.takeDamage(enemyHit)) { //myPlayer.takeDamage returns true if hp <= 0
                playerDied()
                stopCombat() // called before declaration
                mainHandler.removeCallbacks(this) // tried, doesn't work
            }
            playerHP.text = "${myPlayer.currentHitPoints} / ${myPlayer.maxHitPoints}"
            combatLog.append("${myEnemy.name} deals $enemyHit damage!\n")
            mainHandler.postDelayed(this, 3000)
        }
    }

    fun stopCombat(){
        mainHandler.removeCallbacks(performTask)
    }

Upvotes: 0

Views: 617

Answers (2)

Tenfour04
Tenfour04

Reputation: 93629

Set a boolean to determine if you’re going to post the runnable again


override fun run() {
    val enemyHit = enemyAttack(myPlayer, myEnemy)
    val died = myPlayer.takeDamage(enemyHit)) 
    if (died) 
        playerDied()
   playerHP.text = "${myPlayer.currentHitPoints} / ${myPlayer.maxHitPoints}"
            combatLog.append("${myEnemy.name} deals $enemyHit damage!\n")
    if (!died)
        mainHandler.postDelayed(this, 3000)
}

Sorry for formatting—on my phone.

Upvotes: 1

littlebear333
littlebear333

Reputation: 760

I notice that you are using kotlin. I think you can use coroutines. It's more concise and lightweight. Cancellation and Timeouts

If you still want to use thread. Try the following code.

    val executorService = Executors.newSingleThreadExecutor()
    val runnables = Runnable {

    }
    val task = executorService.submit(runnables)
    task.cancel(true)

Upvotes: 1

Related Questions