症狀:游戲過程中,按下Home鍵返回手機主菜單,再點擊游戲圖標試圖返回游戲的時候屏幕黑的一片!
以前一直沒在意只有結束線程在運行游戲,今天覺得改仔細琢磨一下這個問題了!
首先第一件事:打印Logo看看按下Home鍵後會調用哪些方法,結果如下:
游戲過程中按下Home後:
11-29 20:42:07.090: I/System.out(18835): Activity onPause...
11-29 20:42:14.190: I/System.out(18835): Activity onStop...
11-29 20:42:14.260: I/System.out(18835): SurfaceView surfaceDestroyed...
可見SurfaceView 在返回手機主菜單的時候被銷毀了,而我的SurfaceView 主線程是在構造方法裡創建的
那麼我們返回游戲的時候會調哪些方法呢?接著看Log:
11-29 20:48:06.940: I/System.out(18835): Activity onRestart...
11-29 20:48:06.950: I/System.out(18835): Activity onResume...
11-29 20:48:07.230: I/System.out(18835): SurfaceView surfaceCreated...
11-29 20:48:07.240: I/System.out(18835): SurfaceView surfaceChanged...
surfaceDestroyed 的時候線程已經退出了運行,這時再返回到游戲刷屏的線程就沒了,任何繪制方法都沒調用,所以你看到的只有黑漆漆的屏幕啦!
明白了運行原理我們就知道改怎麼做啦!
首先創建線程放在 surfaceCreated ,並啟動線程,
當 surfaceDestroyed 調用的時候,線程已經無效了,我們把線程對象設為null釋放他,
然後不管怎麼返回線程都會繼續運行你的游戲也就不會中斷了,來段簡單的代碼更具表達力度!
- package com.game.view;
-
- import Android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Paint;
- import android.graphics.Paint.Style;
- import android.graphics.Rect;
- import android.view.SurfaceHolder;
- import android.view.SurfaceHolder.Callback;
- import android.view.SurfaceView;
-
- public class TestView extends SurfaceView implements Callback, Runnable{
- public static final int GAME_HEART = 1000/30; //每秒刷新30次
-
- public static int screenW, screenH;
-
- private Thread thread;
- private SurfaceHolder holder;
- private Paint paint;
-
- public TestView(Context context) {
- super(context);
- // TODO Auto-generated constructor stub
- holder = getHolder();
- holder.addCallback(this);
-
- paint = new Paint(Paint.ANTI_ALIAS_FLAG);// 無鋸齒
- paint.setStyle(Style.FILL); //填充樣式
- paint.setTextSize(16); // 字體大小
- }
-
- /**
- * 執行游戲邏輯方法
- */
- private void update() {
-
- }
-
- /**
- * 執行游戲繪制
- */
- private Rect rect = new Rect();
- private void draw(){
- Canvas canvas = holder.lockCanvas();
-
- String text = "天使之翼的示例Demo";
- //獲取文本寬高
- paint.getTextBounds(text, 0, text.length(), rect);
- //在屏幕中央位置顯示文本
- paint.setColor(0xfff000f0); //注意最高兩位 ff 代表畫筆透明度,不設置的畫就是完全透明了,看不到任何效果
- canvas.drawText(text,
- (screenW - rect.width())/2,
- screenH/2 + rect.height()/2,
- paint);
-
- holder.unlockCanvasAndPost(canvas);
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- // TODO Auto-generated method stub
- screenW = getWidth();
- screenH = getHeight();
-
- thread = new Thread(this);
- isRun = true;
- thread.start();
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- // TODO Auto-generated method stub
- //當屏幕旋轉的時候重新獲取屏幕寬高
- screenW = getWidth();
- screenH = getHeight();
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- // TODO Auto-generated method stub
- isRun = false;
- thread = null;
- }
-
- private boolean isRun; //線程運行標志
- private int useTime; //記錄每次刷屏使用的時間
- @Override
- public void run() {
- // TODO Auto-generated method stub
- long start, end;
-
- while(isRun){
- start = System.currentTimeMillis();
- update(); // 刷新界面上所有元素
- draw(); // 繪制界面元素
- end = System.currentTimeMillis();
- useTime = (int) (end - start);
-
- if(useTime < GAME_HEART){ //保證每次刷屏時間間隔相同
- try {
- Thread.sleep(GAME_HEART - useTime);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }
- }