我正在尝试在Kotlin android中进行编码,以每秒移动一次图像,但我无法使其工作。现在,我正在使用Timer
每秒对Timer Task
进行调度,但是它没有按预期工作。
这是我的代码
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)
}
}
}
答案 0 :(得分:0)
您正在尝试在后台线程上更新UI,这是不可能的。 UI只能在UI线程上更新。此外,每隔1秒使用Timer
和TimerTask
创建和销毁线程也不是使用线程的正确方法,因为创建线程是内存消耗大的操作。
您需要做的是使用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)
}
})
以上代码正在使用处理程序,并将任务发布到UI线程消息队列中。任务本身正在更新UI,并使用相同的处理程序将自身重新发布到UI线程消息队列中,但这一次是在handler.postDelayed()
方法的延迟1秒之后
编辑:如何停止可运行
如果要停止特定的runnable
,可以使用以下方法,并传入与runnable
相同的handler.post()
对象。当然,您必须始终保留对runnable
的引用才能停止它。上面的代码没有保留参考。请参见下面的完整代码。
handler.removeCallbacks(runnable) //stops a specific runnable
要停止UI线程消息队列中的所有其余回调或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
答案 1 :(得分:0)
我有一个代码,它按预期运行
val t = object : Thread() {
override fun run() {
while (!isInterrupted) {
try {
Thread.sleep(1000) //1000ms = 1 sec
runOnUiThread {
i++
txt1.text = i.toString()
img_Mario.rotation=180f
img_Mario.translationX +=20
}
} catch (e: InterruptedException) {
e.printStackTrace()
}
}
}
}
bt_down.setOnClickListener {
i=0
t.start()
}