Android GLSurfaceView.Renderer прерывает неполное событие касания
Это проблема, которая у меня возникла некоторое время, и я надеюсь, что кто-то здесь сможет пролить свет на это.
У меня есть игра для Android, которая загружает GLSurfaceView, рендер которого настроен так:
public class GameRenderer implements GLSurfaceView.Renderer
{
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
BaseLib.init(); // Initializes the native code
}
public void onSurfaceChanged(GL10 gl, int width, int height)
{}
public void onDrawFrame(GL10 gl)
{
BaseLib.render(); // Call to native method to render/update the current frame
}
}
Похоже на это:
public class GameView extends GLSurfaceView implements SurfaceHolder.Callback
{
private GameRenderer _renderer;
private GameListener _listener;
public GameView(Context context)
{
super(context);
this._renderer = new GameRenderer();
setRenderer(this._renderer);
this._listener = new GameListener();
BaseLib.setListener(this._listener);
}
public boolean onTouchEvent(final MotionEvent event)
{
int action = -1;
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN: action = 0; break;
case MotionEvent.ACTION_UP: action = 1; break;
case MotionEvent.ACTION_MOVE: action = 2; break;
}
if(action >= 0)
BaseLib.touch(action, event.getX(), event.getY());
return true;
}
}
Я прослеживаю нативный код и замечаю проблему, когда на полпути touch
событие оказывается другим render()
звонок делается. Поскольку сенсорное событие не завершилось, оно приводит к появлению некоторых ошибок из-за того, что оно пытается отобразить объекты, которые еще не завершили загрузку.
Это может быть проблемой в самом нативном коде, но так как я до сих пор не смог найти проблему там, я хотел спросить, возможно ли, что Java-код прерывает вызов touch
и зовет другого onDrawFrame()
до его завершения.
2 ответа
События касания и рендеринг происходят в двух разных потоках. Вы должны правильно синхронизировать ваши данные чтения / записи.
Решение здесь состоит в том, что всякий раз, когда вы захватываете событие касания (которое происходит в потоке пользовательского интерфейса), вы помещаете это же событие в GLSurfaceView как исполняемый файл, и поэтому оно будет выполняться в правильном порядке в потоке средства визуализации GLSurfaceView. Пример кода:
@Override
public boolean onTouchEvent(MotionEvent event)
{
if (event != null)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
if (mRenderer != null)
{
// Ensure we call switchMode() on the OpenGL thread.
// queueEvent() is a method of GLSurfaceView that will do this for us.
queueEvent(new Runnable()
{
@Override
public void run()
{
mRenderer.switchMode();
}
});
return true;
}
}
}
return super.onTouchEvent(event);
}
Учебник с дополнительной информацией по этому вопросу:
http://www.learnopengles.com/listening-to-android-touch-events-and-acting-on-them/