我知道有很多与此类似的问题,但是我找不到我的问题的答案。

我的游戏遇到了麻烦。当SurfaceView的游戏循环正在运行时,我无法更改要使其可见的元素的可见性。

这是因为只有创建视图层次结构的原始线程才能触摸其视图,但是我不知道如何解决它。

07-28 19:07:20.913: E/AndroidRuntime(15091): FATAL EXCEPTION: Thread-26727
07-28 19:07:20.913: E/AndroidRuntime(15091):
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that
created a view hierarchy can touch its views.
07-28 19:07:20.913: E/AndroidRuntime(15091):    at
android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4650)
07-28 19:07:20.913: E/AndroidRuntime(15091):    at
android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:877)
07-28 19:07:20.913: E/AndroidRuntime(15091):    at
android.view.ViewGroup.invalidateChild(ViewGroup.java:4066)
07-28 19:07:20.913: E/AndroidRuntime(15091):    at
android.view.View.invalidate(View.java:10275)
07-28 19:07:20.913: E/AndroidRuntime(15091):    at
android.view.View.setFlags(View.java:8385)
07-28 19:07:20.913: E/AndroidRuntime(15091):    at
android.view.View.setVisibility(View.java:5531)
07-28 19:07:20.913: E/AndroidRuntime(15091):    at
android.widget.ImageView.setVisibility(ImageView.java:1155)
07-28 19:07:20.913: E/AndroidRuntime(15091):    at     com.coderogden.pongtennis.activities.SingleGameActivity.setInVisLife3C(SingleGameActivity.j    ava:84)
07-28 19:07:20.913: E/AndroidRuntime(15091):    at
com.coderogden.pongtennis.views.SingleGameView.outOfBounds(SingleGameView.java:319)
07-28 19:07:20.913: E/AndroidRuntime(15091):    at
com.coderogden.pongtennis.views.SingleGameView.update(SingleGameView.java:197)
07-28 19:07:20.913: E/AndroidRuntime(15091):    at
com.coderogden.pongtennis.other.MainThread.run(MainThread.java:57)


这是代码的重要部分:

活动类包含类似这种方法的负载。

public static void setInVisLife3C() {
        life3C.setVisibility(View.INVISIBLE);
    }


这些方法是从我的SurfaceView类调用的,例如,从这里:

public void outOfBounds() {

    // Player's side
    if (ball.getY() + ball.getRadius() > box.getBoxBot()) {
        playerLives--;
        playing = false;
        switch (playerLives) {
        case 4:
            SingleGameActivity.setInVisLife5P();
            break;
        case 3:
            SingleGameActivity.setInVisLife4P();
            break;
        case 2:
            SingleGameActivity.setInVisLife3P();
            break;
        case 1:
            SingleGameActivity.setInVisLife2P();
            break;
        case 0:
            SingleGameActivity.setInVisLife1P();
            playerLoses();
            break;
        }
    }
}


该方法是从另一个称为update()的方法中调用的,该方法也位于SurfaceView类中!

然后从主线程(游戏循环)中调用update()方法:

@Override
public void run() {
    Canvas canvas;

    while (running) {
        canvas = null;

        // Try locking the canvas
        try {
            canvas = this.surfaceHolder.lockCanvas();
            if (canvas != null) {
                synchronized (surfaceHolder) {
                    // Update game state here!
                    this.gameView.update();
                    More code down here!


请告诉我您是否需要更多代码来帮助我! :)

最佳答案

好吧,你回答了自己的问题。您必须使用runOnUiThread和Runnable对非UI线程中的视图进行更改。例如:

public static void setInVisLife3C() {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            life3C.setVisibility(View.INVISIBLE);
        }
    });
}

07-28 01:11
查看更多