Вы пытаетесь обновить пользовательский интерфейс в фоновом потоке, что невозможно. Пользовательский интерфейс может быть обновлен только в потоке пользовательского интерфейса. Кроме того, использование Timer
и TimerTask
для создания и уничтожения потока каждую 1 секунду не является правильным способом использования потоков, поскольку создание потока является дорогостоящей операцией с памятью.
Вам нужно использовать Handler
и сказать UI Thread
, что нужно запускать Runnable
после каждого требуемого интервала. Удалите Timer
и TimerTask
и используйте следующее
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)
}
})
Приведенный выше код использует обработчик и отправляет задачу в очередь сообщений потока пользовательского интерфейса. Сама задача обновляет пользовательский интерфейс и снова отправляет себя в очередь сообщений потока пользовательского интерфейса, используя тот же обработчик, но на этот раз с задержкой в 1 секунду, используя handler.postDelayed()
methond
РЕДАКТИРОВАТЬ: Как остановить работоспособный
Если вы хотите остановить определенный runnable
, вы можете использовать следующий метод и передать тот же runnable
объект, который вы передали в handler.post()
. Конечно, вы должны всегда сохранять ссылку на runnable
, чтобы остановить его. Приведенный выше код не сохраняет ссылку. См. Полный код ниже.
handler.removeCallbacks(runnable) //stops a specific runnable
Чтобы остановить все оставшиеся обратные вызовы или runnable
из очереди сообщений потока пользовательского интерфейса, используйте эту
handler.removeCallbacksAndMessages(null) //stops any pending callback in message queue
Полный код
ПРИМЕЧАНИЕ: я добавил слушатель щелчка кнопки остановки как дополнение
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)
}
}
}
Подробнее о процессах, потоках и обработчике читайте здесь:
https://developer.android.com/guide/components/processes-and-threads
https://developer.android.com/reference/android/os/Handler