应用程序打开时出现黑屏

4
每次打开我的应用程序时,我都会遇到这个黑屏,唯一的方法是按返回按钮,然后再进入应用程序。我的朋友告诉我这是死锁问题!但我认为不是这个原因,因为当我检查logcat时,它显示以下日志信息。
视图
private boolean mGameIsRunning;

public void surfaceCreated(SurfaceHolder holder) {
    // Your own start method.
    start();

}

public void start() {
    if (!mGameIsRunning) {
        thread.initLevel();
        thread.setRunning(true);
        thread.start();   

        mGameIsRunning = true;
    } else {

        thread.onResume();

        thread.initLevel();
        thread.setRunning(true);
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    Log.d(TAG, "Surface is being destroyed");

    // tell the thread to shut down and wait for it to finish
    // this is a clean shutdown
    boolean retry = true;
    thread.setRunning(false);       
    while (retry) {     
        try {
            thread.join();
            retry = false;  
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }           
    }
    Log.d(TAG, "Thread was shut down cleanly"); 
}

线程

private Object mPauseLock = new Object();  
    private boolean mPaused;
    @Override
    public void run() {
        Canvas canvas;
        Log.d(TAG, "Starting game loop");
        while (running) {
            canvas = null;
            // try locking the canvas for exclusive pixel editing
            // in the surface
            try {
                canvas = this.mSurfaceHolder.lockCanvas();
                synchronized (mSurfaceHolder) {
                    mStartTime = System.currentTimeMillis();
                    mElapsedTime = System.currentTimeMillis() - mStartTime;

                    this.updateGame();
                    this.onDraw(canvas);
                }

                synchronized(mPauseLock){
                    while (mPaused) {

                        try {
                            mPauseLock.wait();
                        } catch (InterruptedException e) {
                        }
                    }   

                }

            } finally {
                // in case of an exception the surface is not left in
                // an inconsistent state
                if (canvas != null) {
                    mSurfaceHolder.unlockCanvasAndPost(canvas);
                }
            }   // end finally          
        }       
    }
    public void onPause() {
        synchronized (mPauseLock) {
            mPaused = true;         
        }
    }

    public void onResume() {
        synchronized (mPauseLock) {
            mPaused = false;
            mPauseLock.notifyAll();
        }
    }

日志

07-08 17:24:41.735: DEBUG/Hitman(3221): View added
07-08 17:24:41.895: DEBUG/(3221): Enemies Spawed
07-08 17:24:41.934: DEBUG/(3221): Starting game loop
07-08 17:24:42.165: INFO/ActivityManager(66): Displayed activity com.android.hitmanassault/.Hitman: 1384 ms (total 1384 ms)
07-08 17:24:46.164: DEBUG/(3221): Enemies Spawed
07-08 17:24:48.914: INFO/ActivityManager(66): Start proc com.android.settings for broadcast com.android.settings/.widget.SettingsAppWidgetProvider: pid=3228 uid=1000 gids={3002, 3001, 3003}
07-08 17:24:48.914: INFO/ActivityManager(66): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.android.launcher/.Launcher }
07-08 17:24:48.924: DEBUG/PhoneWindow(3221): couldn't save which view has focus because the focused view com.android.hitmanassault.HitmanView@44d99528 has no id.
07-08 17:24:48.954: INFO/WindowManager(66): Setting rotation to 0, animFlags=0
07-08 17:24:49.014: INFO/ActivityManager(66): Config changed: { scale=1.0 imsi=310/260 loc=en_US touch=3 keys=2/1/2 nav=3/1 orien=1 layout=34}
07-08 17:24:49.275: DEBUG/(3221): Surface is being destroyed
07-08 17:24:49.285: DEBUG/(3221): Thread was shut down cleanly
07-08 17:24:49.694: DEBUG/ddm-heap(3228): Got feature list request
07-08 17:24:49.754: WARN/IInputConnectionWrapper(3221): showStatusIcon on inactive InputConnection
07-08 17:24:51.315: DEBUG/dalvikvm(66): GC freed 2325 objects / 114696 bytes in 122ms
07-08 17:24:58.234: INFO/ActivityManager(66): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.hitmanassault/.HitmanTitle }
07-08 17:24:58.284: INFO/WindowManager(66): Setting rotation to 1, animFlags=0
07-08 17:24:58.354: INFO/ActivityManager(66): Config changed: { scale=1.0 imsi=310/260 loc=en_US touch=3 keys=2/1/2 nav=3/1 orien=2 layout=34}
07-08 17:24:58.554: DEBUG/(3221): Enemies Spawed
07-08 17:24:58.945: WARN/IInputConnectionWrapper(144): showStatusIcon on inactive InputConnection
07-08 17:25:00.604: DEBUG/dalvikvm(66): GC freed 1403 objects / 71832 bytes in 103ms

活动类:

@Override
    public boolean onCreateOptionsMenu(Menu menu){
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.game_menu, menu);
        return true;
    }

@Override
public boolean onOptionsItemSelected(MenuItem item){

    switch(item.getItemId()){
    case R.id.menu_restart:
        startActivity(new Intent(this, Hitman.class));
        return true;
    case R.id.menu_scores:
        startActivity(new Intent(this, HitmanScores.class));
        return true;
    case R.id.menu_help:
        startActivity(new Intent(this, HitmanHelp.class));
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);   
    setContentView(new CanvasSurfaceView(this));
    Log.d(TAG, "View added");   

}

1
为什么不在应用程序出现黑屏时暂停,并查看您的线程在Eclipse中处于哪一行? - mibollma
@mibollma 我还没有涉及暂停功能,因为我正在尝试让它识别当用户通过主页按钮或应用程序被中断时,它会注意到并允许用户重新打开应用程序而不会强制关闭。如果我更改调用方式,可以编辑代码以显示屏幕而不是黑屏,但我会得到一个强制/等待消息。 - Manji
其实我说的是使用调试器来查看当您得到黑屏时线程所在的代码行。 - mibollma
当应用程序重新打开时,它会出现。 - Manji
2个回答

1
你的线程在哪里初始化?尝试在surfaceCreated()中进行初始化,而不是在surfaceView构造函数中(我认为你是在那里做的..)。
public void surfaceCreated(SurfaceHolder holder) { 

    // Restart draw thread
    Thread.State state = thread.getState();

    if(state == Thread.State.TERMINATED)
        thread = new MyThread(getHolder(), getContext());   
    thread.setRunning(true);
    thread.start();  

} 

不,当我打开应用程序时它强制关闭了。 - Manji

1

旋转显示屏幕是否会导致其刷新(在模拟器中:CTRL+F12)?如果是这样,那么您必须在活动中覆盖onResume()并使其重新启动您设置的任何可能未被调用的内容。也许您只需要从活动onResume()中调用view.invalidate()?由于您没有展示活动代码,因此我不确定。

在我看到的代码中,您应该使用this.postInvalidate()(与invalidate()相同,但来自不同线程)而不是this.onDraw(canvas),并且让它在UI线程中自己调用this.onDraw(),而不是在您的线程中调用。


我在清单文件中将方向设置为横向。如果您需要,我可以发布活动源代码,但它只是调用surfaceview并允许您通过膨胀菜单更改屏幕。 - Manji
@Manji 它从哪里调用SurfaceView?是从onCreate()方法中吗? - Ribose
不完全是这样,它从onCreate()方法中调用surfaceview文件:setContentView(SurfaceView()); - Manji
@Manji 你的意思是setContentView(new SurfaceView())吗?在onCreate()方法中没有其他的设置逻辑(例如告诉SurfaceView要绘制什么)吗?如果有的话,您需要确保在onResume()方法中仍然有这些信息(在您转到另一个活动并返回后调用),和/或调用invalidate()方法使其调用onDraw()从而执行绘图代码。请注意,它也在onCreate()方法之后被调用,因此您甚至可以将这样的逻辑移动到那里。如果没有,我不知道会发生什么。 - Ribose
是的,请看我放在我的活动中的内容,这样你就可以看到了。 - Manji

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接