首先,请注意LunarLander示例完全相同。 无论如何,这很好用,直到我离开应用程序并尝试返回它,然后我得到一个强制关闭(IllegalThreadStateException)。
MainGameActivity:
package com.tests.testgame1;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class MainGameActivity extends Activity {
private static MainGameView mainGameView;
//private static Thread mainGameThread;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainGameView = new MainGameView(getApplicationContext());
//mainGameThread = mainGameView.getThread();
// if (savedInstanceState == null) {
// // we were just launched: set up a new game
// mainGameThread.setState(mainGameThread.STATE_READY);
// Log.w(this.getClass().getName(), "SIS is null");
// } else {
// // we are being restored: resume a previous game
// mainGameThread.restoreState(savedInstanceState);
// Log.w(this.getClass().getName(), "SIS is nonnull");
// }
setContentView(mainGameView);
}
@Override
protected void onStart() {
super.onStart();
// The activity is about to become visible.
}
@Override
protected void onResume() {
super.onResume();
mainGameView.unpauseGame();
// The activity has become visible (it is now "resumed").
}
@Override
protected void onPause() {
super.onPause();
mainGameView.pauseGame();
// Another activity is taking focus (this activity is about to be "paused").
}
@Override
protected void onStop() {
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
@Override
protected void onDestroy() {
super.onDestroy();
// The activity is about to be destroyed.
}
@Override
protected void onSaveInstanceState(Bundle outState) {
// just have the View's thread save its state into our Bundle
super.onSaveInstanceState(outState);
// mainGameThread.saveState(outState);
Log.w(this.getClass().getName(), "SIS called");
}
}
MainGameView:
package com.tests.testgame1;
import android.content.Context;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class MainGameView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "MainGameView"; //
MainGameThread mainGameThread; //
SurfaceHolder mainSurfaceHolder;
Context mainContext;
public MainGameView(Context context) {
super(context);
mainSurfaceHolder = getHolder();
mainSurfaceHolder.addCallback(this);
mainContext = context;
mainGameThread = new MainGameThread(this, mainSurfaceHolder, mainContext);
Log.d(TAG, "View created");
}
public Thread getThread() {
return mainGameThread;
}
public void pauseGame() {
mainGameThread.pauseGame();
}
public void unpauseGame() {
//mainGameThread.start();
mainGameThread.unpauseGame();
}
//
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
if (!hasWindowFocus) mainGameThread.pauseGame();
}
public void onDraw()
{
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
mainGameThread.setRunning(true);
mainGameThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// we have to tell thread to shut down & wait for it to finish, or else
// it might touch the Surface after we return and explode
boolean retry = true;
mainGameThread.setRunning(false);
while (retry) {
try {
mainGameThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
}
MainGameThread:
package com.tests.testgame1;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
class MainGameThread extends Thread {
enum GameStates
{
GameStateRunning,
GameStatePaused
}
private boolean running;
private GameStates gameMode;
private View view;
private Context context;
private SurfaceHolder surfaceHolder;
Bitmap backgroundImage;
public MainGameThread(View _view, SurfaceHolder _surfaceHolder, Context _context)
{
this.view = _view;
this.surfaceHolder = _surfaceHolder;
this.context = _context;
this.running = true;
this.gameMode = GameStates.GameStateRunning;
Resources res = context.getResources();
backgroundImage = BitmapFactory.decodeResource(res, R.drawable.background);
}
public void setRunning(boolean b) {
running = b;
}
@Override
public void run() {
while (running) {
if (gameMode == GameStates.GameStateRunning)
doStep();
Canvas c = null;
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
doDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
synchronized (surfaceHolder) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
private void doDraw(Canvas canvas) {
canvas.drawBitmap(backgroundImage, 0, 0, null);
//canvas.drawColor(Color.BLUE);
}
private void doStep() {
}
public void pauseGame()
{ //
synchronized (surfaceHolder) {
if (gameMode == GameStates.GameStateRunning){
gameMode = GameStates.GameStatePaused;
}
}
}
public void unpauseGame() {
synchronized (surfaceHolder) {
if (gameMode == GameStates.GameStatePaused){
gameMode = GameStates.GameStateRunning;
}
}
}
}
堆栈追踪:
Test Game [Android Application]
DalvikVM[localhost:8625]
Thread [<1> main] (Suspended (exception IllegalThreadStateException))
MainGameView(SurfaceView).updateWindow(boolean) line: 545
MainGameView(SurfaceView).onWindowVisibilityChanged(int) line: 206
MainGameView(View).dispatchWindowVisibilityChanged(int) line: 3891
FrameLayout(ViewGroup).dispatchWindowVisibilityChanged(int) line: 719
LinearLayout(ViewGroup).dispatchWindowVisibilityChanged(int) line: 719
PhoneWindow$DecorView(ViewGroup).dispatchWindowVisibilityChanged(int) line: 719
ViewRoot.performTraversals() line: 744
ViewRoot.handleMessage(Message) line: 1727
ViewRoot(Handler).dispatchMessage(Message) line: 99
Looper.loop() line: 123
ActivityThread.main(String[]) line: 4627
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 521
ZygoteInit$MethodAndArgsCaller.run() line: 868
ZygoteInit.main(String[]) line: 626
NativeStart.main(String[]) line: not available [native method]
Thread [<6> Binder Thread #2] (Running)
Thread [<5> Binder Thread #1] (Running)
Thread [<7> Binder Thread #3] (Running)
答案 0 :(得分:4)
认为您的surfaceCreated方法存在问题。当您退出该线程时,它将被终止。一旦发生这种情况,您就无法拨打电话
mainGameThread.start();
相反,在surfaceCreated中,首先首先查询线程的状态,然后如果它已经终止,则像在MainGameView中那样启动一个新的,
if (mainGameThread .getState() == Thread.State.TERMINATED)
{
mainGameThread = new MainGameThread(this, mainSurfaceHolder, mainContext);
mainGameThread.setRunning(true);
mainGameThread.start();
}
else
{
mainGameThread.setRunning(true);
mainGameThread.start();
}