为什么布局根通过观察者?

时间:2015-07-13 17:52:30

标签: java android

几个小时以来,我一直在使用我的新Android应用程序,但是在一个非常奇怪的例外情况下纠结自己。 意味着异常是明确的,但我不理解其背后的内容。

我有一个名为MainActivity的活动,如下所示:

公共类MainActivity扩展了Activity实现Observer {

 private gameState st = new gameState();
 private gameEngine bc;
 public RelativeLayout gameLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    st.addObserver(this);
    gameLayout = (RelativeLayout) findViewById(R.id.gLayout);
    startGame();

}


@Override
public void update(Observable observable, Object data) {

    int gameState = ((gameState) observable).getState();

    if(gameState == 1){
        continueGame();
    }

    if(gameState == 2){
        killGame();
    }
}

private void killGame(){

    if(!bc.BarThread.isInterrupted()){
    bc.BarThread.interrupt();
    }
    gameLayout.removeAllViewsInLayout();

    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
            LayoutParams.WRAP_CONTENT,
            LayoutParams.WRAP_CONTENT
            );
    TextView tv = new TextView(this);

    gameLayout.addView(tv, params);
    tv.setText("Game Over");
}

}

我的简单gameState类:

public class gameState extends Observable{

private int state = 0;

public gameState() {

}

public void setState(int var){

    synchronized(this){
        state = var;
    }
    setChanged();
    notifyObservers();

}

public synchronized int getState(){

    return state;

}

}

我的gameEngine(实例化为bc),太长了,无法在此发布,但我可以尝试用简单的单词解释内容。

游戏引擎具有一些游戏元素,如按钮,ProgressBar和线程(BarThread),可以持续填充栏。 如果用户成功,则gameEngine将gameState设置为1,MainActivity执行类似killGame()方法的操作,该方法完美无缺。

如果用户太慢且ProgressBar已满,则BarThread将gameState设置为2。 然后MainActivity执行killGame并抛出

 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

但是我无法理解为什么线程会通过观察者产生影响?

1 个答案:

答案 0 :(得分:0)

我在猜BarThread来电setState(int var),对吗?如果这是真的,那么在不是主线程的线程上调用该方法。这意味着setState()调用的所有内容(例如notifyObservers())都未在主线程上调用。我猜测notifyObservers()最终会调用MainActivity.update(Observable observable, Object data),调用killGame(),这会更改视图层次结构(即添加文本视图)。这意味着您的视图层次结构是从不是主线程的线程修改的。

您可能需要在Handler中创建MainActivity。然后在killGame()中,致电Handler.post(Runnable runnable)。像这样:

private Handler handler;

@Override
public void onCreate(Bundle savedInstanceState) {
  handler = new Handler();
}

private void killGame() {
  if(!bc.BarThread.isInterrupted()){
    bc.BarThread.interrupt();
  }

  handler.post(new Runnable() {
    @Override
    public void run() {
      gameLayout.removeAllViewsInLayout();

      RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
        LayoutParams.WRAP_CONTENT,
        LayoutParams.WRAP_CONTENT
      );
      TextView tv = new TextView(MainActivity.this);

      gameLayout.addView(tv, params);
      tv.setText("Game Over");
    }
  });
}
相关问题