我正在尝试在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' touch事件的值是299.0,但在consume方法中,它被更新为509.
我可以想到的一个可能的解释是,当我触摸屏幕时会触发多个触摸事件,并且consumeTouchEvent()
中记录的内容是后来的值 - 但在这种情况下,onTouchEvent()
应该记录所有的触摸值。
如果我在没有产生新线程的情况下运行consumeTouchEvent()
,这个问题就会消失。
答案 0 :(得分:2)
Android framework may reuse instances of MotionEvent
to avoid heap pollution and excessive garbage collection。特别是recycle
方法用于将event
标记为可立即重用:
回收MotionEvent,供以后的调用者重用。调用此功能后,您不能再次触摸该事件。
在您Runnable
创建的onTouchEvent
有机会执行MotionEvent
已经返回之前,Android已重新使用val myEvent = MotionEvent.obtain(event)
// do some work
myEvent.recycle()
实例。
您可以obtain
自己的副本进行处理,如下所示:
val myEvent = MotionEvent.obtain(event)
thread {
if(threadRunning) {
return@Runnable
}
threadRunning = true
consumeTouchEvent(myEvent)
myEvent.recycle()
}
return super.onTouchEvent(event)
您的示例将如下所示:
#include <iostream>
#include <fstream>
int main(int argc, char **argv)
{
std::ifstream is(argv[1]);
for (;;)
{
int x1 = 0, x2 = 0;
char sep = 0;
is >> x1;
is >> sep;
is >> x2;
// Validate the data.
if ((sep != ',') or is.eof()) { break; }
// Data tests valid, use it however.
std::cout << "read: " << x1 << sep << x2 << std::endl;
}
}