在退出应用程序时结束SurfaceView和GameThread

use*_*644 5 multithreading android exit surfaceview

我有一个surfaceview和一个gameThread类.gameThread不断更新和绘制SurfaceView类.

现在,当我退出应用程序时(通过按下主页或后退按钮),我收到一条消息,表明应用程序已关闭.那是因为GameThread仍然试图在擦除的surfaceview上画画......

那么如何在不获得此强制关闭通知的情况下正确结束应用程序?我希望GameThread类在按下后退按钮时停止.当按下主页并在后台运行时它应该暂停.当重新进入仍然运行的游戏时,它应该恢复....

有任何想法吗?

这是我的GameThread类:

public class GameThread extends Thread{

private GameView view;
public boolean isRunning = false;

public GameThread(GameView view) {
    this.view = view;
}

public void setRunning(boolean setRunning) {
    isRunning = setRunning;
}

public void run() {
    while(isRunning) {
        Canvas c = null;
        view.update();
        try {
            c = view.getHolder().lockCanvas();
            synchronized (view.getHolder()) {
                view.draw(c);
            }
        }finally {
            if(c != null) {
                view.getHolder().unlockCanvasAndPost(c);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它不断更新我的GameView类:

公共类GameView扩展了SurfaceView {

private GameThread gameThread;

public GameView(Context context, Activity activity) {
    super(context);
    gameThread = new GameThread(this);
    init();
    holder = getHolder();
    holder.addCallback(new SurfaceHolder.Callback() {

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            gameThread.setRunning(true);
            gameThread.start();

        }
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height) {
        }
    });
}


public void init() {

}

public void update() {

}

public void draw(Canvas canvas) {
    super.draw(canvas);

}
}
Run Code Online (Sandbox Code Playgroud)

当按下home时,我的logcat显示了这个:

02-24 18:24:59.336: E/SurfaceHolder(839): Exception locking surface
02-24 18:24:59.336: E/SurfaceHolder(839): java.lang.IllegalStateException: Surface has already been released.
02-24 18:24:59.336: E/SurfaceHolder(839):   at android.view.Surface.checkNotReleasedLocked(Surface.java:437)
02-24 18:24:59.336: E/SurfaceHolder(839):   at android.view.Surface.lockCanvas(Surface.java:245)
02-24 18:24:59.336: E/SurfaceHolder(839):   at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:872)
Run Code Online (Sandbox Code Playgroud)

主要活动:

public class MainActivity extends Activity {

private RelativeLayout relativeLayout;
private GameView gameView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    gameView = new GameView(this, this);
    setContentView(R.layout.activity_main);
    relativeLayout = (RelativeLayout)findViewById(R.id.mainView);
    relativeLayout.addView(gameView);
}

@Override
public void onBackPressed() {
    // TODO Auto-generated method stub
    super.onBackPressed();
    gameView.onBackPressed();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

}
Run Code Online (Sandbox Code Playgroud)

fad*_*den 2

底层在应用程序生命周期之间和过程中SurfaceSurfaceView破坏。向 中的渲染器线程发送消息,并等待线程关闭。onPause()onDestroy()onPause()

有关示例,请参阅Grafika中的“硬件缩放器练习器”活动。SurfaceHolder它在的回调中启动渲染线程surfaceCreated()

更新:在 中启动线程surfaceCreated()并在 中停止它感觉很奇怪onPause(),因此经过一番重新整理之后,HardwareScalerActivity 现在停止了 中的线程surfaceDestroyed()。(SurfaceView 文档有点含糊——它说 Surface 在“surfaceCreated()surfaceDestroyed()”之间有效——但查看 SurfaceView 实现,这似乎是预期的用法。)

更新2:在发现代码处理不好的情况后,我又更新了代码。现在源码里有60行的大评论,这也可以在我对类似问题的回答中看到。

更新 3:大型评论变成了架构文档附录。Grafika 的“硬件缩放器练习器”活动演示了方法#2,而“来自相机的纹理”则演示了方法#1。