Reputation: 1
I am Alois from Austria. I started with Kotlin to program apps on smartphones 3 days ago, so nearly no glue. I just know vb.net as the latest programming language I started 15 years ago. So hope my english is good enough to explain my problem in detail.
As my first app I wanted to realize an idea from my son. It should become a small game. On the screen you can see 3 buttons (SPEED, UPGRADE and INCOME) on the bottom, in the middle top there is a textView (mytxt) and in the middle a imageView.
Every specific timeperiod (starting with 1s) you earn money, so every second you get 1 piece. This I wanted to program withe a timer/timertask. When I press on the SPEED button, the timeperiod shall get less (in steps of 100ms). But this is my first difficulty, the program crashes without error output by pressing this button.
Please could somebody theck my code an help me with this?
Thanks a lot in advance. Alois
package com.example.uyc_android
import android.annotation.SuppressLint
import android.os.Build
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import java.util.Timer
import java.util.TimerTask
var money=0
var timerperiod: Long= 1000
var computerType=1
var income =1
class MainActivity : AppCompatActivity() {
private lateinit var timer: Timer
private lateinit var timerTask: TimerTask
private var counter = 0
@SuppressLint("SetTextI18n")
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val mytxt = findViewById<TextView>(R.id.txtMoney)
val btnSpeed = findViewById<Button>(R.id.btnSpeed)
val btnUpgrade = findViewById<Button>(R.id.btnUpgrade)
val btnIncome = findViewById<Button>(R.id.btnIncome)
val bild = findViewById<ImageView>(R.id.imagePC)
timer = Timer()
var timerTask = object : TimerTask() {
override fun run() {
counter++
// Aktualisiere den Wert auf der Benutzeroberfläche im UI-Thread
runOnUiThread {
mytxt.text = counter.toString()
}
}
}
timer.schedule(timerTask, 0, timerperiod)
btnSpeed.setOnClickListener {
timerperiod -= 100L
if (timerperiod <= 100L) {
timerperiod = 100L
}
timerTask.cancel()
timer.schedule(timerTask, 0, timerperiod)
runOnUiThread { btnSpeed.text = "SPEED ${timerperiod}" }
}
btnUpgrade.setOnClickListener {
computerType++
if (computerType >= 3) {
computerType = 3
}
if (computerType == 1) {
runOnUiThread { bild.setTag(R.drawable.pc1) }
}
if (computerType == 2) {
runOnUiThread { bild.setTag(R.drawable.pc2) }
}
if (computerType == 3) {
runOnUiThread { bild.setTag(R.drawable.pc3) }
}
runOnUiThread { btnUpgrade.text = "UPGRADE ${computerType}" }
}
btnIncome.setOnClickListener {
income++
runOnUiThread { btnIncome.text = "INCOME ${income}" }
}
}
}
I searched a lot in www. I watched many tutorials but no result. Maybe somebody can change my code so it works.
Upvotes: -1
Views: 880
Reputation: 93852
You cannot reuse TimerTask instances, so you must create a new instance each time. Since it is only used inside onCreate()
, you can define a creator function inside onCreate()
.
By the way, all your uses of runOnUiThread { }
are unnecessary because timer and button listener callbacks are already always called on the UI thread.
fun createTimerTask() = object : TimerTask() {
override fun run() {
counter++
mytxt.text = counter.toString()
}
}
var timerTask = createTimerTask()
timer.schedule(timerTask, 0, timerperiod)
btnSpeed.setOnClickListener {
timerperiod -= 100L
if (timerperiod <= 100L) {
timerperiod = 100L
}
timerTask.cancel()
timerTask = createTimerTask() // <---------------
timer.schedule(timerTask, 0, timerperiod)
btnSpeed.text = "SPEED ${timerperiod}"
}
By the way, this:
timerperiod -= 100L
if (timerperiod <= 100L) {
timerperiod = 100L
}
can be simplified to:
timerPeriod = max(timerPeriod - 100L, 100L)
And your upgrade button listener code can be simplified to:
btnUpgrade.setOnClickListener {
computerType = min(computerType + 1, 3)
btnUpgrade.text = "UPGRADE ${computerType}"
val tag = when (computerType) {
1 -> R.drawable.pc1
2 -> R.drawable.pc2
3 -> R.drawable.pc3
else -> return
}
bild.setTag(tag)
}
Upvotes: 0