I am trying to code in kotlin android to move an image every second but I am not able to make it work. Right now I'm using a Timer to schecule a Timer Task every second but it is not working as expected.
Here is my code
class Actvt_Image<float> : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_actvt__image)
        val pict_mario = findViewById<ImageView>(R.id.img_Mario)
        val bt_down = findViewById<Button>(R.id.bt_down)
        val frame = findViewById<LinearLayout>(R.id.frame)
        val txt1=findViewById<TextView>(R.id.txt1)
        var i =100
        val timer = Timer()
        val myTask = object : TimerTask() {
            override fun run() {
                txt1.text = (i+1).toString()
                img_Mario.rotation=180f
                img_Mario.translationX +=100
                img_Mario.translationY +=20
            }
        }
        bt_down.setOnClickListener {
            i=0
            timer.schedule(myTask, 1000, 1000)
        }
    }
}
                You are trying to update the UI on a background thread which is not possible. UI can only be updated on the UI thread. Also, using a Timer and TimerTask to create and destroy a thread every 1 second is not the right way to use threads because creating a thread is a memory expensive operation.
What you need to do is to use a Handler and tell the UI Thread to run a Runnable after every desired interval. Remove Timer and TimerTask and use the following 
val handler = Handler(Looper.getMainLooper())
handler.post(object : Runnable {
            override fun run() {
                txt1.text = (i+1).toString()
                img_Mario.rotation=180f
                img_Mario.translationX +=100
                img_Mario.translationY +=20
                handler.postDelayed(this, 1000)
            }
        })
Above code is using a handler and posting a task to the UI Thread message queue. The task itself is updating the UI and posting itself again to the UI Thread message queue using the same handler but this time after 1 second delay using the handler.postDelayed() methond
EDIT : How to stop runnable
If you want to stop a specific runnable you can use the following method and pass in the same runnable object that you passed in handler.post(). Surely you have to keep a reference to the runnable at all time to stop it. The above code doesn't keep a reference. See the Complete code below.
handler.removeCallbacks(runnable) //stops a specific runnable
To stop all remaining callbacks or runnable from the UI Thread message queue use this 
handler.removeCallbacksAndMessages(null) //stops any pending callback in message queue
Complete code
NOTE: I have added a stop button click listener as an addition
class Actvt_Image<float> : AppCompatActivity() {
        private lateinit var handler : Handler
        private lateinit var runnable : Runnable // reference to the runnable object
        private var i = 0
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_actvt__image)
            val pict_mario = findViewById<ImageView>(R.id.img_Mario)
            val bt_down = findViewById<Button>(R.id.bt_down)
            val bt_stop = findViewById<Button>(R.id.bt_stop)
            val frame = findViewById<LinearLayout>(R.id.frame)
            val txt1=findViewById<TextView>(R.id.txt1)
            handler = Handler(Looper.getMainLooper())
            runnable = Runnable {
                i++
                txt1.text = i.toString()
                img_Mario.rotation=180f
                img_Mario.translationX +=100
                img_Mario.translationY +=20
                handler.postDelayed(runnable, 1000)
            }
            bt_down.setOnClickListener {
                handler.post(runnable)
            }
            bt_stop.setOnClickListener {
                //Use this to stop all callbacks
                //handler.removeCallbacksAndMessages(null)
                handler.removeCallbacks(runnable) 
            }
        }
    }
Read more about processes, threads and handler here : https://developer.android.com/guide/components/processes-and-threads https://developer.android.com/reference/android/os/Handler
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With