在线程中运行的Kotlin使用的值不同于传递的值

我想在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 } 

触摸视图后,这是相应的日志:

 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,但是在消费方法中,它被更新为509。

我可以想到的一个可能的解释是,当我触摸屏幕时触发多个触摸事件,并且consumeTouchEvent()是稍后的值 – 但是在这种情况下, onTouchEvent()应该记录所有的触摸值。

如果我不运行一个新的线程运行consumeTouchEvent()这个问题就消失了。

Android框架可以重用MotionEvent实例,以避免堆积污染和垃圾收集 。 特别是使用recycle方法将event标记为立即可用于重用:

回收MotionEvent,以供稍后调用者重新使用。 调用此函数后,您不能再次触摸该事件。

在您创建的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)