我正在尝试在 Android 上运行一个线程,代码如下:
override fun onTouchEvent(event: MotionEvent?): Boolean {
Log.d("CustomImage", " touched : ${event!!.x}, ${event.y}")
Thread(Runnable {
if(threadRunning) {
return@Runnable
}
threadRunning = true
consumeTouchEvent(event)
}).start()
return super.onTouchEvent(event)
}
private fun consumeTouchEvent(event: MotionEvent) {
Log.d("CustomImage", " consumeTouchEvent x,y : ${event.x}, ${event.y}")
Thread.sleep(1000) //long running task
threadRunning = false
}
这是我触摸 View 后的相应日志:
01-03 00:17:05.654 8122-8122/me.exp D/CustomImage: touched : 960.0, 299.0
01-03 00:17:05.656 8122-8250/me.exp D/CustomImage: consumeTouchEvent x,y : 960.0, 509.0
很明显,触摸事件的“Y”值是 299.0,但在 consume 方法中,它被更新为 509。
我能想到的一个可能的解释是,当我触摸屏幕时会触发多个触摸事件,并且 consumeTouchEvent()
中记录的内容是稍后的值 - 但在那种情况下,onTouchEvent( )
应该记录所有触摸值。
如果我在不生成新线程的情况下运行 consumeTouchEvent()
,这个问题就会消失。
最佳答案
Android framework may reuse instances of MotionEvent
to avoid heap pollution and excessive garbage collection . recycle
方法特别用于将 event
标记为可立即重用:
Recycle the MotionEvent, to be re-used by a later caller. After calling this function you must not ever touch the event again.
在您创建的 Runnable
有机会执行之前,onTouchEvent
已经返回,因此 Android 已经重用了 MotionEvent
实例。
您可以 obtain
您自己的副本,以便像这样进行处理:
val myEvent = MotionEvent.obtain(event)
// do some work
myEvent.recycle()
您的示例将如下所示:
val myEvent = MotionEvent.obtain(event)
thread {
if(threadRunning) {
return@Runnable
}
threadRunning = true
consumeTouchEvent(myEvent)
myEvent.recycle()
}
return super.onTouchEvent(event)
关于android - 线程中的 Kotlin runnable 使用的值与传递的值不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48072263/