Domanda

I have this code in a class named GameLoop (code similar to the LunarLander sample)

while( running ) {
    Canvas canvas = null;
    try {
        canvas = mSurfaceHolder.lockCanvas(null);
        long t = System.currentTimeMillis();
        if( t - old[0] >= frame ) {
            old[0] = t;
            synchronized( mSurfaceHolder ) {
                mGame.update();
                mGame.onDraw(canvas);
            }
        }
    }
    finally {
        // Do this in finally so that if an exception is thrown
        // we don't leave the Surface in an inconsistent state
        if( canvas != null ) mSurfaceHolder.unlockCanvasAndPost(canvas);
    }

        }

The parent class is GameView (reference mGame).
When mGame.update() tries to call his own announce method,

public class GameView extends SurfaceView implements SurfaceHolder.Callback {

. . .
    private void announce(int resId) {
        synchronized( mSurfaceHolder ) {
            tv_announcement.setText(getContext().getString(resId));
            ObjectAnimator anim = ObjectAnimator.ofFloat(tv_announcement, "alpha", 0, 1);
            anim.setDuration(ANNOUNCE_DURATION).start();
        }
    }
. . .

I get this exception:

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

There are two thread here, the UI thread, which runs GameView and owns the SurfaceView, and GameLoop which is an extension of Thread and only runs the update-draw loop.

As I understand it, the exception is telling me that only the UI thread can touch the TextView tv_announcement.
But isn't announce running in the UI thread? What am I missing here?

Here is the logcat of the exception after announce:

03-22 07:20:19.096: D/GameView(28250): + update(): state:IDLE, next state:CHOOSE_SIDE
03-22 07:20:19.096: D/GameView(28250): + announce(resId:2131361803)
03-22 07:20:19.096: W/dalvikvm(28250): threadid=10: thread exiting with uncaught exception (group=0xb3040180)
03-22 07:20:19.096: E/AndroidRuntime(28250): FATAL EXCEPTION: Thread-192
03-22 07:20:19.096: E/AndroidRuntime(28250): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4039)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:709)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.view.View.requestLayout(View.java:12675)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.view.View.requestLayout(View.java:12675)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.view.View.requestLayout(View.java:12675)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.view.View.requestLayout(View.java:12675)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.view.View.requestLayout(View.java:12675)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:268)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.view.View.requestLayout(View.java:12675)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.widget.TextView.checkForRelayout(TextView.java:6773)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.widget.TextView.setText(TextView.java:3306)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.widget.TextView.setText(TextView.java:3162)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at android.widget.TextView.setText(TextView.java:3137)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at <package>.GameView.announce(GameView.java:436)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at  <package>.GameView.update(GameView.java:314)
03-22 07:20:19.096: E/AndroidRuntime(28250):    at  <package>.GameView$GameLoop.run(GameView.java:495)
03-22 07:20:19.126: D/GameView(28250): + onWindowFocusChanged(hasWindowFocus:true)
03-22 07:20:19.126: D/GameView(28250): - onWindowFocusChanged()
È stato utile?

Soluzione

Only the original thread that created a view hierarchy can touch its views.

Your error is thrown because for sure you are modifying UI from not UI Thread probably from worker Thread.

If you want to update UI with some information from operation performed in Thread or just from some process performed in Thread you can only use:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top