Android GLSurfaceView.Renderer прерывает неполное событие касания - PullRequest
2 голосов
/ 26 февраля 2011

Это проблема, с которой я столкнулся некоторое время, и я надеюсь, что кто-то здесь сможет пролить свет на это.

У меня есть игра для 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 ]

5 голосов
/ 27 февраля 2011

События касания и рендеринг происходят в двух разных потоках. Вы должны правильно синхронизировать данные для чтения / записи.

1 голос
/ 09 марта 2012

Решение здесь состоит в том, что всякий раз, когда вы захватываете событие касания (которое происходит в потоке пользовательского интерфейса), вы помещаете это же событие в 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/

...