Home > Mobile >  Why does my code does not update the number on the screen
Why does my code does not update the number on the screen

Time:05-28

what the function does is deviding the numertor with the denomirator and updates the app's text view accordingly after every second, the problem is that it doesn't update the screen its just simply shows the original number of the numerator that is 60. what do I change in order to make this work?

fun division() {
    val numerator = 60
    var denominator = 4
    repeat(4) {
        Thread.sleep(1_000)
        findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
        denominator--
    }
}

CodePudding user response:

Because you are setting (basically overwritting) the text everytime it loops through, you will only see the value of the last increment which would be 60/1 and that's why you are only seeing 60 value. Try like this:

fun division() {
    val numerator = 60
    var denominator = 4
    repeat(4) {
        Thread.sleep(1_000)
        findViewById<TextView>(R.id.division_textview).append("${numerator / denominator}\n")
        denominator--
    }
}

setText() was overwriting the text with the new one but append() is gonna keep the previous text.

CodePudding user response:

This is that dang Codelab again isn't it? I knew it looked familiar... I already answered a similar question here - but basically, when you run division on the main thread (which you must be since you're messing with UI components), you're freezing the app because you're blocking the thread with Thread.sleep

The display can't actually update until your code has finished running, i.e. after you exit the division function, because it's all running on the same thread, and the display update pass comes later. So this is what's actually happening:

  • freeze the app for 1 second
  • set the text as the result of 60 / 4 - it won't actually redraw until later, after your code has finished, so there's no visual change
  • freeze the app for 1 second
  • set the text as the result of 60 / 3 - again you won't see anything happen yet, but now it's going to show 60 / 3 instead of 60 / 4, because you just updated the state of that TextView
  • etc.

The last text you set is the result of 60 / 1, and then your code finishes, so the system can finally get around to updating the display. So the first thing you see after the app stops freezing is 60 - it's not just the numerator, it's the last calculation from your loop.

If you want something to update while the app is running, there are lots of solutions like coroutines, CountdownTimers, posting runnables that execute at a specific time, etc. The answer I linked shows how to create a separate thread to run basically the same code on, so you can block it as much as you like without affecting the running of the app. The one thing you don't do is block the main thread like that Codelab example does. It's a bad Codelab

CodePudding user response:

You can use delay and then call from a coroutine:

private suspend fun division() {
    val numerator = 60
    var denominator = 4
    repeat(4) {
        delay(1000)
        findViewById<TextView>(R.id.division_textview).text = "${numerator / denominator}"
        denominator--
    }
}

Then from your Activity/Fragment:

lifecycleScope.launch {
    division()
}
  • Related