Android 如何每秒运行Runnable更新UI
我试图在kotlin android中编写代码,以便每秒移动一幅图像,但我无法使其正常工作。现在我正在使用一个Android 如何每秒运行Runnable更新UI,android,kotlin,Android,Kotlin,我试图在kotlin android中编写代码,以便每秒移动一幅图像,但我无法使其正常工作。现在我正在使用一个计时器每秒调度一个计时器任务,但它没有按预期工作 这是我的密码 class Actvt_Image<float> : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)
计时器
每秒调度一个计时器任务
,但它没有按预期工作
这是我的密码
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)
}
}
}
class activt\u Image:appcompativity(){
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity\u actvt\u图像)
val pict_mario=findViewById(R.id.img_mario)
val bt_down=findviewbyd(R.id.bt_down)
val frame=findViewById(R.id.frame)
val txt1=findviewbyd(R.id.txt1)
变量i=100
val timer=timer()
val myTask=object:TimerTask(){
覆盖趣味跑(){
txt1.text=(i+1).toString()
旋转角度=180华氏度
img_Mario.translationX+=100
img_Mario.translationY+=20
}
}
bt_down.setOnClickListener{
i=0
时间表(myTask,10001000)
}
}
}
您试图在后台线程上更新UI,这是不可能的。UI只能在UI线程上更新。另外,使用定时器
和定时器任务
每1秒创建和销毁一个线程并不是使用线程的正确方法,因为创建线程是一个内存开销很大的操作
您需要做的是使用处理程序
并告诉UI线程
在每个所需的间隔后运行Runnable
。移除定时器
和定时器任务
并使用以下命令
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.postdayed()
method延迟1秒
编辑:如何停止可运行
如果要停止特定的runnable
,可以使用以下方法并传入与传入handler.post()
相同的runnable
对象。当然,您必须始终保持对runnable
的引用才能停止它。上面的代码没有保留引用。请参见下面的完整代码
handler.removeCallbacks(runnable) //stops a specific runnable
要停止UI线程消息队列中所有剩余的回调或runnable
,请使用以下命令
handler.removeCallbacksAndMessages(null) //stops any pending callback in message queue
完整代码
注意:我添加了一个停止按钮click listener作为添加
class activt\u Image:appcompativity(){
私有lateinit变量处理程序:处理程序
private lateinit var runnable:runnable//对runnable对象的引用
私有变量i=0
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity\u actvt\u图像)
val pict_mario=findViewById(R.id.img_mario)
val bt_down=findviewbyd(R.id.bt_down)
val bt_stop=findviewbyd(R.id.bt_stop)
val frame=findViewById(R.id.frame)
val txt1=findviewbyd(R.id.txt1)
handler=handler(Looper.getMainLooper())
可运行的{
我++
txt1.text=i.toString()
旋转角度=180华氏度
img_Mario.translationX+=100
img_Mario.translationY+=20
handler.postDelayed(可运行,1000)
}
bt_down.setOnClickListener{
handler.post(可运行)
}
bt_stop.setOnClickListener{
//使用此选项停止所有回调
//handler.removeCallbacksAndMessages(null)
handler.removeCallbacks(可运行)
}
}
}
在此处阅读有关进程、线程和处理程序的更多信息:
我有一个代码,它按照我的预期运行
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()
}
定义“无法工作”尝试在您的ClickListener中调用timer.run(),它无法按预期移动它是否移动?你想如何移动?我想移动image_mario,但它不能。这也会起作用,但问题是你正在创建一个新线程,并要求该线程在UI线程上运行一段代码,而自己什么也不做。简言之,如果新线程没有做任何其他事情,那么就不需要创建新线程。相反,您可以使用UI线程本身来运行一段代码,方法是使用
handler.post()
,正如我在回答中提到的。您的代码是正确的。但我如何控制它何时可以运行。示例:当我单击一个按钮,然后它将运行时?@danghang只需在bt\u down.setOnClickListener
之前初始化处理程序,然后将其余代码放入bt\u down.setOnClickListener
中。我编辑了我的答案,看到了完整的代码。@DangHoang我的错,我忘了添加那个。检查我的最新答案。这次不是直接在handler.post()方法中创建runnable
对象。我一直将它作为单独的runnable
对象进行引用,并使用它来启动和停止runnable
@danghang我很高兴听到这个消息。如果此解决方案对您有效,请单击复选标记图标,将答案勾选为已接受。祝你好运
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()
}