Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么布局根通过观察者?_Java_Android - Fatal编程技术网

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

Java 为什么布局根通过观察者?,java,android,Java,Android,几个小时以来,我一直在使用我的新安卓应用程序,但却遇到了一个非常奇怪的例外。 这意味着例外是明确的,但我不理解它背后的内容 我有一个名为MainActivity的活动,如下所示: 公共类MainActivity扩展了活动实现{ private gameState st = new gameState(); private gameEngine bc; public RelativeLayout gameLayout; @Override protected void onCreate(B

几个小时以来,我一直在使用我的新安卓应用程序,但却遇到了一个非常奇怪的例外。 这意味着例外是明确的,但我不理解它背后的内容

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

公共类MainActivity扩展了活动实现{

 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");
}
}

我的简单游戏状态类:

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;

}
}

我的游戏引擎被实例化为bc,太长了,无法在这里发布,但我可以尝试用简单的语言解释内容

游戏引擎具有一些游戏元素,如按钮、进度条和线程,这些元素不断填充进度条。 如果用户成功,gameEngine会将gameState设置为1,MainActivity会执行类似killGame方法的操作,这非常有效

如果用户速度太慢且进度条已满,则BarThread会将游戏状态设置为2。 然后MainActivity执行killGame和抛出

 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
但是我不明白为什么线程会通过观察者产生影响?

我猜BarThread调用setStateint var,对吗?如果这是真的,那么在不是主线程的线程上调用该方法。这意味着setState调用的所有内容(例如NotifyObservators)都不会在主线程上调用。我猜NotifyObservators最终会调用MainActivity.updateObservable observable对象数据,这会调用killGame,这会更改视图层次结构,即添加文本视图。这意味着您的视图层次结构是从非主线程的线程修改而来的

您可能需要在MainActivity中创建一个处理程序。然后在killGame中,调用Handler.postRunnable。大概是这样的:

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");
    }
  });
}

您的答案看起来很好,但是如何设置TextView的上下文,因为“this”现在是可运行的,而不是MainActivity?您应该能够使用MainActivity.this。另一个选项是在handler.post调用外部创建TextView。您需要将其设置为final,然后您应该能够在handler.post中简单地调用最后两行addView和setText