2

这是我一直有一段时间的问题,我希望这里的某个人能够对此有所了解。

我有一个 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()

4

2 回答 2

5

触摸事件和渲染发生在两个不同的线程上。您必须正确同步数据读/写。

于 2011-02-26T21:10:30.673 回答
1

此处的解决方案是,每当您捕获触摸事件(发生在 UI 线程上)时,您将相同的事件作为可运行对象加入 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/

于 2012-03-09T19:37:21.893 回答