以半传统方式,我有一个活动游戏(MainActivity),只有一个表面视图(MainSurface)。我设置了两个“游戏状态”,它们将自己渲染到表面视图画布(SplashState和ModelState)。
当应用程序启动时,表面视图将自己移到飞溅状态,以便它可以像这样将自己绘制到屏幕上。
SurfaceHolder holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
initInput();
if(currentState == null){
setCurrentState(new SplashState());
}
initApp();
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
pauseApp();
}
});
private void pauseApp(){
running = false;
while(appThread.isAlive()){
try{
appThread.join();
break;
} catch (InterruptedException e){
}
}
}
当用户触摸启动画面时,它会调用SurfaceView将状态更改为ModelState(这是应用程序的主要状态)
@Override
public boolean onTouch(MotionEvent e, int scaledX, int scaledY) {
setCurrentState(new ModelState());
return false;
}
所有这一切都很有效。但是,当我让我的设备睡眠,或使用其他应用程序然后打开我的应用程序,有时我得到ModelState,有时我得到SplashState。有谁能解释为什么?我觉得当应用程序暂停和恢复时,我应该做更多的事情来保存应用程序的当前状态,所以它肯定会重新开始在同一个位置。任何帮助将不胜感激。
答案 0 :(得分:2)
如果您只想保存用户看到的状态(模型或启动),您可以覆盖onPause和onResume来保存和检索状态。当应用程序进入后台时,OnPause和onResume是唯一保证被调用的两种方法,因此saveInstanceState和restoreInstanceState可能不适合你。
尝试使用SharedPreferences对象保存用户所处的状态。这是一个例子:
@Override
protected void onPause() {
super.onPause();
sharedPreferences = getSharedPreferences(KEY_SHARED_PREFERENCES, 0);
SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit();
sharedPreferencesEditor.putString(STATE_KEY, currentState);
sharedPreferencesEditor.commit();
}
@Override
protected void onResume() {
super.onResume();
sharedPreferences.getString(MODEL_KEY, null)
}
答案 1 :(得分:1)
行为的部分原因与SurfaceView的工作方式有关。它的生命周期与通常的Activity生命周期略有不同。
an appendix to the Graphics Architecture doc中讨论了这种现象。简而言之,系统试图避免破坏和重新创建表面。如果您旋转设备,您将获得暂停/恢复和销毁/创建。如果您只是让设备进入睡眠状态并将其唤醒,并且锁定屏幕不会强制进行旋转更改,您将获得暂停/恢复但不会破坏/创建。
诀窍在于以适合决斗生命周期的方式管理渲染线程和资源分配(特别是打开和关闭相机)。
有两种基本方法:(1)在Activity上启动/停止线程 启动/停止; (2)在Surface创建/销毁上启动/停止线程。
该文件继续解释每个方法的含义,以及何时必须采取其他行动。两种方法的例子都可以在Grafika中找到;来自相机的#34;纹理"活动使用#1,而"硬件缩放器训练器"活动使用#2。
回到你的代码,你从pauseApp()
打电话给surfaceDestroyed()
。由于无法保证表面会被销毁,因此当应用暂停时,您的pauseApp()
代码可能无法运行。添加一些日志记录到各种状态更改函数,并在导航设备时在logcat中查看它们(或不激活)。