同类型游戏 生命周期 讲解的博客还有 :从零开始Android游戏编程(第二版) 第九章 游戏程序的生命周期

书本上, 网络上android游戏框架比比皆是, 但是都未深入其生命周期, 下面只适用于 单机版,网络版好像不适用

以下是我选取的基于servaceView的android游戏框架,

Activity

  1 GameActivity.java  2  package air.frame;  3    4  import android.app.Activity;  5  import android.os.Bundle;  6  import android.util.Log;  7  import android.view.Menu;  8  import android.view.MenuItem;  9  import android.widget.TextView; 10   11  publicclass GameActivity extends Activity { 12  private GameSurfaceView gameSurfaceView; 13  private GameThread gameThread; 14  publicstaticfinal String TAG ="GameFrame"; 15       16      @Override 17  publicvoid onCreate(Bundle savedInstanceState) { 18  super.onCreate(savedInstanceState); 19          setContentView(R.layout.main); 20          gameSurfaceView = (GameSurfaceView) this.findViewById(R.id.gameview); 21          gameThread = gameSurfaceView.getThread(); 22          gameSurfaceView.setTextView((TextView) findViewById(R.id.textview)); 23           24          Log.d(TAG, "onCreate"); 25           26  if (savedInstanceState ==null) { 27  // 游戏第一次启动时,初始化游戏状态 28              gameThread.doStart(); 29              Log.d(TAG, "SIS is null"); 30          } else { 31  // 从其他应用界面切回游戏时,如果Activity重新创建,则恢复上次切出游戏时的各项数据 32              gameThread.restoreState(savedInstanceState); 33              Log.d(TAG, "SIS is not null"); 34          } 35      } 36   37  /** 38       * 当Activity被切换到后台时调用,存储Activity重新创建时需要恢复的游戏数据 39  */ 40      @Override 41  protectedvoid onSaveInstanceState(Bundle outState) { 42  super.onSaveInstanceState(outState); 43          gameThread.saveState(outState); 44          Log.d(TAG, "SIS called"); 45      } 46   47  /** 48       * 当Activity被切换到后台时调用,在这里对游戏做"暂停"的处理 49  */ 50      @Override 51  protectedvoid onPause() { 52  super.onPause(); 53  // 暂停游戏 54          Log.d(TAG, "onPause"); 55          gameSurfaceView.getThread().pause(); 56      } 57   58  /** 59       * 当Activity切换到前台时调用 60  */ 61      @Override 62  protectedvoid onResume() { 63  super.onResume(); 64  // 游戏结束暂停状态,游戏正常进行 65          Log.d(TAG, "onResume"); 66          gameSurfaceView.getThread().unpause(); 67      } 68   69  /** 70       * 创建游戏菜单 71  */ 72      @Override 73  publicboolean onCreateOptionsMenu(Menu menu) { 74  // TODO Auto-generated method stub 75          Log.d(TAG, "onCreateOptionsMenu"); 76  returnsuper.onCreateOptionsMenu(menu); 77      } 78   79  /** 80       * 定义游戏菜单的点击事件处理 81  */ 82      @Override 83  publicboolean onOptionsItemSelected(MenuItem item) { 84  // TODO Auto-generated method stub 85          Log.d(TAG, "onOptionsItemSelected"); 86  returnsuper.onOptionsItemSelected(item); 87      } 88   89      @Override 90  protectedvoid onRestart() { 91          Log.d(TAG, "onRestart"); 92  super.onRestart(); 93      } 94   95      @Override 96  protectedvoid onRestoreInstanceState(Bundle savedInstanceState) { 97          Log.d(TAG, "onRestoreInstanceState"); 98  super.onRestoreInstanceState(savedInstanceState); 99      }100  101      @Override102  protectedvoid onStart() {103          Log.d(TAG, "onStart");104  super.onStart();105      }106  107      @Override108  protectedvoid onStop() {109          Log.d(TAG, "onStop");110  super.onStop();111      }112  113      @Override114  protectedvoid onDestroy() {115  super.onDestroy();116          Log.d(TAG, "onDestroy");117  118  // 停止游戏119          gameThread.setRunning(false);120  boolean retry =true;121  while (retry) {122  try {123  // 阻塞Activity的主线程直到游戏线程执行完124                  gameThread.join();125                  retry =false;126              } catch (InterruptedException e) {127              }128          }129      }130  }

surfaceView

GameSurfaceView.java
 1  GameSurfaceView.java 2  package air.frame; 3   4  import android.content.Context; 5  import android.os.Handler; 6  import android.os.Message; 7  import android.util.AttributeSet; 8  import android.util.Log; 9  import android.view.KeyEvent;10  import android.view.SurfaceHolder;11  import android.view.SurfaceView;12  import android.view.SurfaceHolder.Callback;13  import android.widget.TextView;14  15  publicclass GameSurfaceView extends SurfaceView implements Callback {16  private GameThread gameThread;17  private TextView textview;18  19  final String TAG = GameActivity.TAG;20      21  public GameSurfaceView(Context context, AttributeSet attrs) {22  super(context, attrs);23          SurfaceHolder holder = getHolder();24          holder.addCallback(this);25          gameThread =new GameThread(holder, context, new Handler() {26              @Override27  publicvoid handleMessage(Message m) {28                  textview.setText(m.getData().getString("text"));29              }30          });31  // 设置可获得焦点,确保能捕获到KeyEvent32          setFocusable(true);33      }34  35  /**36       * 获取一个Activity传来的View协助SurfaceView显示游戏视图,View的具体类型可以根据游戏需要来定37  */38  publicvoid setTextView(TextView view) {39  this.textview = view;40      }41  42  public GameThread getThread() {43  return gameThread;44      }45  46      @Override47  publicboolean onKeyDown(int keyCode, KeyEvent event) {48  return gameThread.doKeyDown(keyCode, event);49      }50  51      @Override52  publicboolean onKeyUp(int keyCode, KeyEvent event) {53  return gameThread.doKeyUp(keyCode, event);54      }55  56  /**57       * 当SurfaceView得到或失去焦点时调用,使游戏暂停/恢复运行,58  */59      @Override60  publicvoid onWindowFocusChanged(boolean hasWindowFocus) {61  if (!hasWindowFocus) {62              gameThread.pause();63          } else {64              gameThread.unpause();65          }66      }67  68      @Override69  publicvoid surfaceChanged(SurfaceHolder holder, int format, int width,70  int height) {71          Log.d(TAG, "surfaceChanged()");72          gameThread.setSurfaceSize(width, height);73          gameThread.setRunning(true);74  if (gameThread.isAlive()) {75              Log.v(this.getClass().getName(), "unpause gameThread");76              gameThread.unpause();77          } else {78              Log.v(this.getClass().getName(), "start gameThread");79              gameThread.start();80          }81      }82  83      @Override84  publicvoid surfaceCreated(SurfaceHolder holder) {85          Log.d(TAG, "surfaceCreated()");86      }87  88  /**89       * 为防止surface还会被创建(比如来电)导致gameThread再次启动出现错误,且Activity的onPause方法中已做暂停处理,90       * 这边不对gameThread做处理91       * 92       * @param holder93  */94      @Override95  publicvoid surfaceDestroyed(SurfaceHolder holder) {96          Log.d(TAG, "surfaceDestroyed");97      }98  }

游戏控制线程

GameThread.java
  1 GameThread.java  2  package air.frame;  3    4  import android.content.Context;  5  import android.graphics.Canvas;  6  import android.os.Bundle;  7  import android.os.Handler;  8  import android.util.Log;  9  import android.view.KeyEvent; 10  import android.view.SurfaceHolder; 11   12  publicclass GameThread extends Thread { 13  final String TAG = GameActivity.TAG; 14       15  // 游戏状态值:ready 16  publicfinalstaticint GS_READY =0; 17  // 游戏线程每执行一次需要睡眠的时间 18  privatefinalstaticint DELAY_TIME =100; 19  // 上下文,方便获取到应用的各项资源,如图片、音乐、字符串等 20  private Context context; 21  // 与Activity其他View交互用的handler 22  private Handler handler; 23  // 由SurfaceView提供的SurfaceHolder 24  private SurfaceHolder surfaceHolder; 25  // 游戏线程运行开关 26  privateboolean running =false; 27  // 游戏状态 28  privateint gameState; 29  // 当前surface/canvas的高度,在surfaceChanged方法中被设置 30  privateint mCanvasHeight =1; 31  // 当前surface/canvas的宽度,在surfaceChanged方法中被设置 32  privateint mCanvasWidth =1; 33   34  /** 35       * 游戏是否暂停 36  */ 37  privateboolean isPaused =false; 38   39  public GameThread(SurfaceHolder holder, Context context, Handler handler) { 40  this.surfaceHolder = holder; 41  this.context = context; 42  this.handler = handler; 43      } 44   45  /** 46       * 设置游戏状态 47       *  48       * @param mode 游戏状态 49  */ 50  publicvoid setState(int mode) { 51  synchronized (surfaceHolder) { 52              setState(mode, null); 53          } 54      } 55   56  /** 57       * 设置游戏状态 58       *  59       * @param mode 游戏状态 60       * @param message 设置游戏状态时的附加文字信息 61  */ 62  publicvoid setState(int mode, CharSequence message) { 63  synchronized (surfaceHolder) { 64  // TODO 65          } 66      } 67   68  /** 69       * 暂停游戏 70  */ 71  publicvoid pause() { 72  synchronized (surfaceHolder) { 73              isPaused =true; 74          } 75      } 76   77  /** 78       * 恢复运行游戏 79  */ 80  publicvoid unpause() { 81  // 如果游戏中有时间,别忘记应将其在这里调整到正常 82  synchronized (surfaceHolder) { 83              isPaused =false; 84          } 85      } 86   87  /** 88       * 当Activity因销毁而被重新创建时,在这里恢复游戏上次运行的数据 89       *  90       * @param saveState Activity传来的保存游戏数据的容器 91  */ 92  publicvoid restoreState(Bundle saveState) { 93  // TODO 94      } 95   96  /** 97       * 在Activity切到后台时保存游戏的数据 98       *  99       * @param outState 保存游戏数据的容器100  */101  publicvoid saveState(Bundle outState) {102  // TODO103      }104  105  /**106       * 设置游戏线程运行开关107       * 108       * @param b 开/关109  */110  publicvoid setRunning(boolean b) {111          running = b;112      }113  114  /**115       * 处理按下按键的事件116       * 117       * @param keyCode 按键事件动作值118       * @param msg 按键事件对象119       * @return 是否处理完120  */121  publicboolean doKeyDown(int keyCode, KeyEvent msg) {122  synchronized (surfaceHolder) {123  // TODO124  returnfalse;125          }126      }127  128  /**129       * 处理弹起按键的事件130       * 131       * @param keyCode 按键事件动作值132       * @param msg 按键事件对象133       * @return 是否处理完134  */135  publicboolean doKeyUp(int keyCode, KeyEvent msg) {136  synchronized (surfaceHolder) {137  // TODO138          }139  returnfalse;140      }141  142  /**143       * 设置surface/canvas的宽度和高度144       * 145       * @param width 由SurfaceHolder传来的宽度146       * @param height 由SurfaceHolder传来的高度147  */148  publicvoid setSurfaceSize(int width, int height) {149  // synchronized to make sure these all change atomically150  synchronized (surfaceHolder) {151              mCanvasWidth = width;152              mCanvasHeight = height;153  // 不要忘记每次画布的宽度和高度改变时, 在这里对图片等资源做缩放等相关适配屏幕的处理154  // TODO155          }156      }157  158  publicvoid run() {159  while (running) {160  if (!isPaused) {161                  Canvas c =null;162  try {163                      c = surfaceHolder.lockCanvas(null);164  synchronized (surfaceHolder) {165                          doDraw(c);166                      }167                      logic();168                  } finally {169  if (c !=null) {170                          surfaceHolder.unlockCanvasAndPost(c);171                      }172                  }173  try {174                      Thread.sleep(DELAY_TIME);175                  } catch (InterruptedException e) {176                      e.printStackTrace();177                  }178              }179          }180      }181  182  /**183       * 游戏逻辑处理184  */185  publicvoid logic() {186          Log.v(this.getClass().getName(), "logic");187  // TODO188      }189  190  /**191       * 游戏绘画192  */193  privatevoid doDraw(Canvas canvas) {194          Log.v(this.getClass().getName(), "doDraw");195  // TODO196      }197  198      199  /**200       * 初始化游戏开始时的参数201  */202  publicvoid doStart() {203  // TODO204      }205  }

布局文件

main.xml
 1 <?xml version="1.0" encoding="utf-8"?> 2 <FrameLayout 3     xmlns:android="http://schemas.android.com/apk/res/android" 4     android:orientation="vertical" 5     android:layout_width="fill_parent" 6     android:layout_height="fill_parent"> 7     <air.frame.GameSurfaceView 8         android:id="@+id/gameview" 9         android:layout_width="fill_parent"10         android:layout_height="fill_parent"/>11     <RelativeLayout12         android:layout_width="fill_parent"13         android:layout_height="fill_parent">14         <TextView15             android:id="@+id/textview"16             android:layout_width="wrap_content"17             android:layout_height="wrap_content"18             android:layout_centerInParent="true"19             android:gravity="center_horizontal"20             android:textColor="#88ffffff"21             android:textSize="24sp"/>22     </RelativeLayout>23 </FrameLayout>

生命周期初步信息

如上所示:surfaceView的生命周期寄托在activity的生命周期之上

附:

activity现场保护:(可以用于实现游戏暂停, 也可以持久化存储现场, 在surfaceCreate里面判断恢复)

http://www.cnblogs.com/wumao/archive/2011/04/25/2026483.html

以下链接是恢复现场的几种方法!

http://www.cnblogs.com/xirihanlin/archive/2009/08/05/1539420.html

除了官方的生命周期图之外, 如下链接对生命周期的见解, 我觉得不错!

http://www.cnblogs.com/kofi1122/archive/2011/04/10/2011772.html

另外, 两个不常用的状态:

onSaveInstanceState: Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key) /当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按返回键的时候。

onSaveInstanceState触发的时机

1、当用户按下HOME键时。

这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则


2、长按HOME键,选择运行其他的程序时。


3、按下电源按键(关闭屏幕显示)时。


4、从activity A中启动一个新的activity时。


5、屏幕方向切换时,例如从竖屏切换到横屏时。

在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行

总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。

onRestoreInstanceState:需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执


另外,onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原(如例子所示Line25~Line33)。

更多相关文章

  1. Android中解决手机屏幕横竖屏切换问题
  2. Android横屏竖屏切换的问题
  3. android context
  4. android AsyncTask类的使用
  5. Android中onInterceptTouchEvent与onTouchEvent(图文)! .
  6. Android如何调用第三方SO库
  7. android core dump测试
  8. Android学习——Activity生命周期
  9. android 调用图库中选择的图片

随机推荐

  1. SQL Server 中 存储“经纬度”应设置的数
  2. pymysql实现从a表过滤出有效信息添加至b
  3. Python爬取京东评论(多线程+队列+bs4+pymy
  4. MySQL选择哪个列不是空的。
  5. 在细队共数细军精文候只就
  6. repcached与mysql缓存測试
  7. 类型不敏感的nvarchar类型的主键,其中ß!=
  8. 设置mysql5.7远程连接
  9. Linux服务器安装php之后连接MySQL数据失
  10. 如何限制SQL Server中的用户登录尝试