【问题标题】:Android Implementing runOnUiThreadAndroid 实现 runOnUiThread
【发布时间】:2014-07-28 18:54:51
【问题描述】:

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

我的游戏出现问题。当 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)

这是代码的重要部分:

Activity-class 包含大量类似的方法。

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!

如果您需要更多代码来帮助我,请告诉我! :)

【问题讨论】:

    标签: java android android-activity graphics


    【解决方案1】:

    嗯,你回答了你自己的问题。您必须使用 runOnUiThreadRunnable 来更改非 UI 线程中的视图。例如:

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

    【讨论】:

    • 谢谢!但问题是:“无法从 Activity 类型对非静态方法 runOnUiThread(Runnable) 进行静态引用”。并且该方法必须是静态的才能从另一个类访问(我从我的 SurfaceView 类访问它)?
    • @CoderOgden 如果理解正确,您的 SurfaceView 类应该有一个上下文引用,您可以将其转换为 Activity。或者,您可以将处理程序传递给您包装的自定义 SurfaceView 以回调到 Activity。
    • 对不起,我想你在第一句话中就把我弄丢了,我是 android 编程新手...
    • @CoderOgden 同样,调用这样的活动方法是不好的做法,您应该考虑使用活动引用来调用它们。
    • 好的,谢谢!这是正确的方法吗? [stackoverflow.com/questions/11656879/…(卢克·泰勒回答)
    【解决方案2】:

    您不能从 UI 线程调用 runOnUiThread。您需要从单独的线程中调用它。试试这个

    编辑@Gintas_答案:

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

    【讨论】:

    • 这与我评论 Gintas_ 答案的原因不同,对不起。
    猜你喜欢
    • 2017-09-22
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多