从OpenGL线程使用Handler.dispatchMessage时挂起/崩溃



我正在为Android开发一款opengl游戏。当用户松开游戏时,应该返回主菜单,但这个调用是从OpenGl ES线程到UI线程进行的,存在一些问题。我在renderer和另一个使用queueEvent()的类之间发现了这个post-Pass变量,并尝试在以下代码中添加Handler类:

public class GameActivity extends Activity {
    private GLSurfaceView gameView;
    private int menuViewID;
    private Handler gameOverHandler;
    public GameActivity () {
        super();
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        gameOverHandler = new Handler() {
            public void handleMessage (Message msg){
                handleGameOver();
            }
        };
        gameView = new GameView(this, gameOverHandler);
        menuViewID = R.layout.main;
        setContentView(menuViewID);
    }
    /** Called when the user selects the Send button */
    public void startGame(View view) {
        setContentView(gameView);
        gameView.setVisibility(View.VISIBLE);
    }
    private void handleGameOver() {
        /**
         * TODO: switch back to main menu
         */
//      setContentView(menuViewID);         // after this gameView freezes
//      gameView.setVisibility(View.GONE);  // after this application throw an error: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

    }
}

然后稍后在OpenGL ES代码中

gameOverHandler.dispatchMessage(Message.obtain(gameOverHandler));

但我仍然得到了一个冻结或运行时异常(请参阅上面代码中的注释行)。我在这里错过了什么或做错了什么?

顺便问一下,如何获得在XML中定义的View实例的引用(请参阅上面代码中的menuViewID),或者为什么findViewById方法返回NULL

您不希望使用dispatchMessage(msg)方法。这显然与直接调用处理程序相同。(文档很差。它似乎是为系统使用而准备的)。

请参阅此处的类似问题:

Handler.dispatchMessage(msg)和Handler.sendMessage(msg)之间的差异

相反,你可以使用这个:

gameOverHandler.obtainMessage(MY_MSG_INT_ID).sendToTarget();

你必须在UI线程中处理它吗?我可以使用以下代码从我的游戏类中很好地处理它:

    Intent myIntent = new Intent(myContext, EndGameActivity.class);
    ((Activity)getContext()).startActivityForResult(myIntent, 0);

我只是将UI线程活动中的上下文强制转换回一个活动,然后从那里开始我的新活动以获得结果。我发回一个结果,然后在UI线程上的活动中,我捕捉到这样的结果:

    @Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    if (resultCode == 1) { 
       this.finish(); 
    }
} 

最新更新