UI线程在执行期间停止正常工作

时间:2019-04-29 01:31:34

标签: java android multithreading user-interface

我正在使用Java开发Android游戏。当用户单击一个按钮来启动一个线程时,该线程会执行一连串的射击和弹跳操作,并通过sleep(20)和this.invalidate()进行一段时间,以实时显示该事件。我还试图引入一个守护进程线程来负责动画。我注意到,随着第二个线程的引入,UI线程在程序执行期间会中断。中断的时间取决于许多因素。但是,一旦它崩溃,就会发现以下情况:

  • activity.runOnUiThread(new Runnable(){内的代码将停止执​​行。
  • 当切换到另一个应用并返回操作栏和通知栏时,它们不再消失。因此,这段代码也停止执行:

    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
    
  • 关闭应用程序并再次启动它会导致其冻结,并出现黑屏。

但是,以下方法仍然有效: *动画仍然可以正确显示 *拍摄和弹跳仍然有效,并且显示正确且没有滞后。 *杀死该应用程序并重新启动它会暂时修复它。

以下情况似乎导致运行时中断:

  1. 额外的动画线程的介绍。

    public void animThread() {

    animThread = new Thread ( new Runnable( ) {
        public void run( )
        {
    
        while(true)
        {
            animation();
        }
    
    
        }
    } );
    
    animThread.setDaemon(true);
    animThread.setPriority(3);
    animThread.start();
    

    }

    private void animation() {     if(powerups.isEmpty()== false)     {         同步(通电)         {             对于(Powerup pw:powerups)             {                 if(pw.isActivated()== false)pw.rotate();             }         }

    }
    
    this.invalidate();
    
    
    try {
        if(Units.animPause==true)
        {
    
            synchronized (Units.animSync) {
                while (Units.animPause) {
                    try {
                        Units.animSync.wait();
                    } catch (InterruptedException e) {
                        System.out.println("interrupt");
                    }
                }
            }
    
        }
        else {
    
            Thread.sleep(20);                //delay before next cycle
        }
    
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    

    }

优先级,守护进程,用于检查线程是否应该等待的if语句没有任何区别。如果没有单个activity.runOnUiThread调用,就会发生此问题。

  1. 如果我从拍摄线程过于频繁地调用activity.runOnUiThread。即使没有动画线程,也会发生相同的问题。 我什至用以下代码替换了所有的拍摄代码以进行测试:

    public void testshoot() {     // int count = 0;     while(计数器<100)     {

        counter++;
        System.out.println("counter: " + counter);
        if(counter % 2 == 0)
        {
            gw.activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("game over run");
                    System.out.println("counter: 1: " + counter);
                    gw.activity.findViewById(R.id.GameOver).setVisibility(View.VISIBLE);
                    ((TextView)gw.activity.findViewById(R.id.Score)).setText("Your Score: " + counter);
                    System.out.println("game over run1");
                }
            });
        }
    
        try {
            if(Units.isPaused==true)
            {
                synchronized (Units.pauseSync) {
                    while (Units.isPaused) {
                        try {
                            Units.pauseSync.wait();
                        } catch (InterruptedException e) {
                            System.out.println("interrupt");
                        }
                    }
                }
    
            }
            else {
    
                Thread.sleep(20);                //delay before next cycle
            }
    
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    
    }
    
    counter=0;
    

    }

将会发生什么,菜单将显示在屏幕上,并且计数器将开始正确地递增,直到它停止更新为止,这是因为runOnUiThread内部的代码由于某些问题而停止执行。降低呼叫频率似乎可以推迟甚至消除问题。例如if(计数器%10 == 0)

  1. 如果我将第1点的动画线程与从第2点调用runOnUiThread结合起来,则该问题会更快出现。

我的onPause和onResume:

public void onPause()
{
    if(Units.isPaused == false)
    {
        Units.adHocPause=true;
        synchronized (Units.pauseSync) {
            Units.isPaused = true;
        }
    }

    synchronized (Units.animSync) {
        Units.animPause = true;
    }

    super.onPause();
}

@Override
public void onResume(){
    //System.out.println("is paused: " + Units.isPaused);
    if(Units.adHocPause==true)
    {
        Units.adHocPause=false;
        synchronized (Units.pauseSync) {
            Units.isPaused = false;
            Units.pauseSync.notifyAll();
        }
    }
    else
    {
        View menu = findViewById(R.id.Menu);
        menu.setVisibility(View.VISIBLE);
        synchronized (Units.pauseSync) {
            Units.isPaused = true;
        }
    }

    synchronized (Units.animSync) {
        Units.animPause = false;
        Units.animSync.notifyAll();
    }


    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
    super.onResume();
}

我想了解当我的应用程序中的某些内容在运行时中断时到底会发生什么,它是什么原因,是什么原因导致的,以及如何避免这种情况发生。我对使方案1起作用很感兴趣。我包括了场景2和3,因为希望它们能给我们一个提示,让它打破。

0 个答案:

没有答案