0

このコード

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)

getPointerId0からインデックスを取得することが文書化されているため、これはまったく不可能に思えます(文書getPointerCount()-1を参照)。

私が知っている唯一の奇妙なことは、処理のためにGLサーフェスのレンダリングスレッドにGLSurfaceView.queueEventを渡すために使用することです。MotionEvent

public boolean onTouchEvent(final MotionEvent event)
{
    queueEvent(new Runnable() {
        public void run() {
            worker.handleTouchEvent(event);
        }
    });
    return true;
}

不変であると思われるオブジェクトへの参照を取得しており、読み取り専用アクセスのみを行っている別のスレッドに安全に渡して処理していると思います。

したがって、実際のMotionEventオブジェクトにアクセスするコードをUIスレッドに移動しますが、問題が発生することは非常にまれであるため、アプリが出荷されるまで、問題を本当に修正したかどうかはわかりません。

質問:ここで本当に何が問題になっていますか?

フォローアップの質問:これがマルチスレッドの使用に関係していると仮定すると、MotionEventを別のスレッドに安全に送信するにはどうすればよいですか?

4

2 に答える 2

0

さらにテストを重ねた結果、onTouchEvent が返された後、Android フレームワークが実際に MotionEvent オブジェクトを再利用していることを確信しました。

したがって、イベント オブジェクトを不変オブジェクトと見なしてはなりません。特に、イベント処理関数の最後を超えて保持したり、別のスレッドに渡したりしないでください。

于 2013-05-07T18:41:49.693 に答える