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 show60 / 3
instead of60 / 4
, because you just updated the state of thatTextView
- 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, CountdownTimer
s, post
ing 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()
}