此代码
android.view.MotionEvent event = ...;
for(int i = 0, n = event.getPointerCount(); i < n; i++)
{
handleTouch(event.getPointerId(i), event.getX(i), event.getY(i));
}
零星地抛出IllegalArgumentException
:
09-03 19:43:21.996 E/AndroidRuntime( 9484): FATAL EXCEPTION: GLThread 732
09-03 19:43:21.996 E/AndroidRuntime( 9484): java.lang.IllegalArgumentException: pointerIndex out of range
09-03 19:43:21.996 E/AndroidRuntime( 9484): at android.view.MotionEvent.nativeGetPointerId(Native Method)
09-03 19:43:21.996 E/AndroidRuntime( 9484): at android.view.MotionEvent.getPointerId(MotionEvent.java:1927)
这似乎是不可能的,因为getPointerId
被记录为从0 getPointerCount()-1
获取指数(见the documentation)。
我所知道的唯一奇怪的事情是我使用GLSurfaceView.queueEvent
将MotionEvent
传递给GL表面的渲染线程进行处理:
public boolean onTouchEvent(final MotionEvent event)
{
queueEvent(new Runnable() {
public void run() {
worker.handleTouchEvent(event);
}
});
return true;
}
我正在获取一个我认为应该是不可变的对象的引用,我想我正安全地将它传递给另一个线程进行处理,我只进行只读访问。
因此我将访问实际MotionEvent对象的代码移动到UI线程,但由于问题很少发生,我不知道在应用程序发布之前我是否真正解决了问题。
问题:这里到底出了什么问题?
后续问题:假设这与我使用多线程有关,如何我如何安全地将MotionEvent发送到另一个线程?
答案 0 :(得分:0)
根据您提到的the documentation,您需要在getX(),getY()的调用中使用从findPointerIndex()获得的索引:
for (int i = 0, n = event.getPointerCount(); i < n; i++)
{
int pid = event.getPointerId(i);
int index = event.findPointerIndex(pid);
if (index != -1)
{
handleTouch(pid, event.getX(index), event.getY(index));
}
}
答案 1 :(得分:0)
经过进一步测试,我现在确信Android框架确实在onTouchEvent返回后重新使用了MotionEvent对象。
因此,不能将事件对象视为不可变对象;特别是,它不应该保持在事件处理函数的末尾之外,或者传递给另一个线程。