2012-09-03 43 views
0

此代碼getPointerId拋出異常,即使指數在範圍

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.queueEventMotionEvent傳遞給GL表面的渲染線程處理:

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

我得到一個對象的引用,我認爲應該是不可變的,我認爲我安全地將它傳遞給另一個線程進行處理,在那裏我只進行只讀訪問。

我因此移動訪問實際MotionEvent對象到UI線程的代碼,但因爲只有極少發生的問題,我不知道我是否真正解決了這一問題,直到應用船舶。

問題:什麼是真的錯了嗎?

後續問題:假設這與我使用多線程做,如何做安全的MotionEvent發送到另一個線程?

回答

0

進一步測試後,我現在確信Android框架確實在onTouchEvent返回後重新使用MotionEvent對象。

因此,事件對象不能被認爲是不可變的對象;特別是它不應該超出事件處理函數的末尾,或者傳遞給另一個線程。

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)); 
    } 
} 
+0

編號findPointerIndex正好與getPointerId相反。因此,event.findPointerIndex(event.getPointerId(i))== i。 – wolfgang