setContentView()在一个线程内

时间:2011-07-25 21:30:53

标签: java android android-layout

我正在制作一个用Java编写的简单Android游戏。

我有我的活动......

public class GameName extends Activity{
...
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
}

在“主”布局中,我有一个调用“startTheGame”方法的按钮:

public void startTheGame(View v) {
theGame = new Panel(this);
    setContentView(theGame);
}

这是面板代码(简化)

class Panel extends SurfaceView implements SurfaceHolder.Callback {
  public GameThread _thread;
    public Panel(Context context) {
      super(context);
      getHolder().addCallback(this);
      setFocusable(true);
    } 
  ...
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        _thread = new GameThread(getHolder(), this);
        _thread.setRunning(true);
        _thread.start();
    }
 ...
 }

因为你可以看到我有一个“GameThread”课程已经开始......这里是下面的内容:

class GameThread extends Thread {
    private SurfaceHolder _surfaceHolder;
    private Panel _panel;
    private boolean _run = false;

    public GameThread(SurfaceHolder surfaceHolder, Panel panel) {
        _surfaceHolder = surfaceHolder;
        _panel = panel;
    }

    public void setRunning(boolean run) {
        _run = run;
    }
            @Override
    public void run() {
        Canvas c;
        while (_run) {
            c = null;

            try {
                    ...

                    if (health <= 0) {
                        _run = false;

                        //change views?
                        setContentView(R.layout.over);

                    }

                    c = _surfaceHolder.lockCanvas(null);
                    synchronized (_surfaceHolder) {
                        _panel.onDraw(c);                       
                    }

                    ...

                } finally {
                    // do this in a finally so that if an exception is
                    // thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        _surfaceHolder.unlockCanvasAndPost(c);
                    }
                    try {
                        Thread.sleep(60);
                    } catch (Exception e) {
                    }
                }


            }

        }

希望您可以看到,如果运行状况为&lt; = 0,则会停止该线程,我正在尝试更改为我创建的另一个名为“over”的布局。

它只是阻止屏幕更新(绘图),但我从未见过新面板。

我试过了:

GameName cs = ((GameName)getApplicationContext())
cs.setContentView(R.layout.over);

但我得到了ClassCastException ......

请帮助!

2 个答案:

答案 0 :(得分:0)

我建议使用Handlers。它允许您安全地与UI线程进行通信,而无需担心您当前使用的是哪个线程。

答案 1 :(得分:0)

您无法将ApplicationContext强制转换为主ActivityGameName),因为这不是同一个对象。在某种程度上,getApplicationContext()与第一个推出的Activity不对应,而是与应用本身相对应。

对我来说,您应该尝试进行不同的活动,而不是尝试更改单个Activity的布局和行为。这对你来说会更简单,它可以避免你遇到的那种问题。 实际上,我在代码中看到的每个setContentView()都应该对应一个开关。

通过这种方式,您可能会遇到以下情况:

  • WelcomeActivity(可能GameName此处):选择游戏选项并开始
  • PlayingActivity:游戏本身。这就是实际游戏玩法的地方。
  • GameOverActivity:显示比赛结果或游戏结束后您想要展示的任何内容

这不知道你正在做什么类型的游戏,但这个骨架应该适用于街机/动作,角色扮演/冒险甚至迷宫/神游戏。