android - MotionEvent 在仍在使用时被回收

标签 android multithreading surfaceview touch-event motionevent

我正在使用 SurfaceView 将触摸绘制为覆盖在我的应用程序上。我希望我的其他 View 能够与 SurfaceView 同时响应触摸事件,因此在包含的 ViewGroup 中他们都是我添加的

我的 View 组:

@Override
public boolean onInterceptTouchEvent(MotionEvent motionEvent){
    mSurfaceView.onTouchEvent(motionEvent);
    return false;
}

由于 SurfaceView 位于其他 View 的后面,因此效果很好。 SurfaceView 和它上面的 View 都会收到 MotionEvent

然后 SurfaceView 进一步将事件转发给渲染到其中的线程。

我的表面 View :

@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
    if (mThreadHandler != null){
        mThreadHandler.sendMotionEvent(motionEvent);
    }
    return true;
}

然后当我的渲染线程收到它运行的消息时:

我的渲染线程:

private void handleMotionEvent(MotionEvent motionEvent){
    switch (motionEvent.getAction()){
        case MotionEvent.ACTION_DOWN:
            float x = motionEvent.getX();                          // Breakpoint 1
            float x2 = motionEvent.getX();                         // Breakpoint 2
            float x3 = motionEvent.getX();                         // Breakpoint 3
            path.moveTo(motionEvent.getX(), motionEvent.getY());
            break;
        case MotionEvent.ACTION_MOVE:
            path.lineTo(motionEvent.getX(),motionEvent.getY());
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
                // do nothing
            break;
        default:
            break;
   }
}

当我在 Debug模式下运行此代码并在 ViewGroup 上滑动手指时,xx2 的值x3 都不同。我怀疑这是因为 UI 线程在被 MyRenderThread 使用之前重新使用了 MotionEvent。我该如何解决这个问题?

糟糕的解决方案是将每个 MotionEvent 复制为一个新对象并将其传递给 MyRenderThread,但这需要很多对象创建/销毁。

最佳答案

MotionEvent.obtain(MotionEvent ev) 将从作为输入事件副本的池中返回一个 MotionEvent

我的 View 组:

@Override
public boolean onInterceptTouchEvent(MotionEvent motionEvent){
    mSurfaceView.fowardTouchEvent(MotionEvent.obtain(motionEvent); 
    return false;
}

我的表面 View :

public void forwardTouchEvent(MotionEvent motionEvent){
    if (scratchpadThreadHandler != null){
        scratchpadThreadHandler.sendMotionEvent(motionEvent);
    }
}

我的渲染线程:

private void handleMotionEvent(MotionEvent motionEvent){
    switch (motionEvent.getAction()){
        case MotionEvent.ACTION_DOWN:
            float x = motionEvent.getX();                          // Breakpoint 1
            float x2 = motionEvent.getX();                         // Breakpoint 2
            float x3 = motionEvent.getX();                         // Breakpoint 3
            path.moveTo(motionEvent.getX(), motionEvent.getY());
            break;
        case MotionEvent.ACTION_MOVE:
            path.lineTo(motionEvent.getX(),motionEvent.getY());
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
                // do nothing
            break;
        default:
            break;
   }
    motionEvent.recycle();  // Mark this MotionEvent as available for recycling.
}

这样每个事件仍然被复制(不知道该怎么做)但至少对象被重用。

关于android - MotionEvent 在仍在使用时被回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25942640/

相关文章:

android - SurfaceView 与自定义 View (从 View 扩展)。 SurfaceView 比较慢,为什么?

android - 使用选项卡在 ActionBar 中调用 onCreateOptionsMenu 的次数太多

Android OpenCV 在 Optimus black (GB) 中对空白屏幕进行示例

c++ - 编译器内存屏障和互斥量

java - 队列不适用于线程?

java - 错误 : createWindowSurface failed EGL_BAD_ALLOC

android - Robolectric:使用 ormlite 进行测试

java - 每 3 秒更新一次 TextView 值

c++ - 如何使用 pthreads 对类成员函数进行多线程处理?

android - 使用 android camera2 在相机预览中显示矩形并在其中裁剪图像