我正在为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();
}
}