【问题标题】:How to save current activity's status when some other activity comes to the foreground当其他一些活动进入前台时如何保存当前活动的状态
【发布时间】:2013-09-12 20:45:00
【问题描述】:

我正在构建我的第一个 Android 应用程序,这是一个棋盘游戏,由 ImageViews(可拖动)、ToggleButton(打开/关闭声音)、TextViews(用于得分)、ArrayList、布尔值、整数、字符串、浮点数和一些双打。如果我按返回按钮进入主菜单,并尝试返回我正在玩的游戏,它会崩溃。我没有实现任何 onPause、onStop、onRestart、onResume。我只实现了onCreate。我浏览了该网站上的几篇文章,但所有答案都令人困惑。我应该使用 onPause 和 onResume 或 onSaveInstanceState 和 onRestoreInstanceState 来保存我当前的游戏状态(所有数据类型和对象)。一个例子将不胜感激。

提前致谢!!

我的日志猫

09-12 16:13:06.326: E/AndroidRuntime(14207): FATAL EXCEPTION: main
09-12 16:13:06.326: E/AndroidRuntime(14207): java.lang.RuntimeException: Unable to resume activity {com.example.baghchalNepal/com.example.baghchal.UserAsTiger}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2851)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2880)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2302)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.app.ActivityThread.access$700(ActivityThread.java:152)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1282)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.os.Handler.dispatchMessage(Handler.java:99)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.os.Looper.loop(Looper.java:137)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.app.ActivityThread.main(ActivityThread.java:5328)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at java.lang.reflect.Method.invokeNative(Native Method)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at java.lang.reflect.Method.invoke(Method.java:511)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at dalvik.system.NativeStart.main(Native Method)
09-12 16:13:06.326: E/AndroidRuntime(14207): Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.view.ViewGroup.addViewInner(ViewGroup.java:3435)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.view.ViewGroup.addView(ViewGroup.java:3306)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.view.ViewGroup.addView(ViewGroup.java:3251)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.view.ViewGroup.addView(ViewGroup.java:3227)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at com.example.baghchal.UserAsTiger.makeGoatMove(UserAsTiger.java:683)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at com.example.baghchal.UserAsTiger.onResume(UserAsTiger.java:297)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1202)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.app.Activity.performResume(Activity.java:5328)
09-12 16:13:06.326: E/AndroidRuntime(14207):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2841)
09-12 16:13:06.326: E/AndroidRuntime(14207):    ... 12 more

Java 代码

    // create ImageView object to store a goat.
    ImageView thisGoat = null;          
    
    // This method call receives safest position where a goat can be placed.
    Point bestPoint = getBestPointToPlaceGoat();

    // if there are goats remained to be placed on the board, select a goat to be moved to the board.
    for (int i=0; i<imageArrayList.size(); i++) {
        if ((imageArrayList.get(i).getX() == (xMin+70)) &&  (imageArrayList.get(i).getY() == (yMin-200))){
            thisGoat = imageArrayList.get(i);
            break;
        }
    }
    
    // move the goat, if a goat was selected from above.
    if (thisGoat != null) {         

         // Here I am removing the ImageView obj
        relativeLayout.removeView(thisGoat);  

        thisGoat.setX(bestPoint.getX()-70);
        thisGoat.setY(bestPoint.getY()-70);
        bestPoint.setOccupiedBy("goat");            
        
         // this is where error is acc. to logcat
        relativeLayout.addView(thisGoat);           
    }

【问题讨论】:

  • - A:您应该使用 Activity 生命周期方法来保存任何数据并在 Activity 发生状态更改时清理正在使用的任何资源。 - B:你收到的错误是什么?你能发布一个 Logcat 吗?
  • 你的意思是onPause,onStop,...通过Activity生命周期方法吗?我并没有真正使用任何特殊资源,只是我猜想通过存储数据类型和对象来存储我在问题中所述的 RAM。我在原始问题中添加了 logcat 错误。
  • 根据您的 Logcat:错误位于 UserAsTiger 类的第 683 行。在 Logcat 中查找 Caused by: java.lang.IllegalStateException: The specified child already has a parent 的行。您必须先在孩子的父母上调用 removeView()。
  • 检查一下,我添加了发生错误的代码的 sn-p,我在添加之前从布局中删除视图。
  • 如何删除视图?在上面的代码中,错误中提到的那一行是哪一行?

标签: android android-activity state


【解决方案1】:

如果我按返回按钮进入主菜单,并尝试返回我正在玩的游戏,它会崩溃。

如果唯一的问题是当您按下后退按钮时,如您所说,那么您可以覆盖后退按钮并在那里保存数据

@Override
public void onBackPressed()
{
    // save your data here using SharedPrefs, DB, or however you need
}

您不需要实现onResume(),因为您的Activity 将被终止,onCreate() 将再次被调用,您可以在其中检查存储的数据并恢复您的值。

如果您担心另一个Activity 何时出现在前台但当前Activity 仍在堆栈中,那么您可以以相同的方式覆盖onPause() 并将数据保存在该函数中。

如果这些都没有帮助,那么如 Prmths 的评论中所述,请发布您的 logcat,以便我们查看错误是什么。

Activity Docs with lifecycle example

【讨论】:

  • 是的,只有当我点击返回按钮进入主菜单,然后再次点击游戏按钮继续游戏时才会发生这种情况。我想,根据你的说法,如果我实现 onBackPressed() 应该没问题。我真的不需要保存在数据库上,所以我猜 SharedPrefs 是 wtg。
  • 现在看到您的 logcat,您可能需要调用 removeView() 来删除您尝试添加的任何视图(在 Views 父级上调用它)。如果这不能解决您的问题,那么您需要发布一些相关代码
  • 检查一下,我在发生错误的地方添加了一个 sn-p 代码,并且在添加之前我从布局中删除了视图。
  • @amir0220 这仅在您按下返回按钮时发生?如果是这样,请将relativeLayout.removeView(thisGoat) 放入onBackPressed() 并将这两个变量都设为成员变量。
  • 除了我上面的评论,使用山羊时要小心。他们可能非常狡猾
【解决方案2】:

这些方法将完全为您使用

您可以使用 SharedPreferences 保存数据并 onResume 将其取回 从here了解更多信息

@Override
protected void onResume()
{       
    super.onResume();
}
@Override
protected void onPause()
{
    super.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState)
{
    // Save your data here
    super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
    super.onRestoreInstanceState(savedInstanceState);       
     // REtrieve your data heve
}

您将了解更多关于Activity Life Cycle

【讨论】:

  • 我明白所有这些,而且我的活动中确实有这些方法,只是通过调用超级方法,这没有任何帮助。
  • @amir0220 为什么暂停时您可以将值保存在 SharedPrefernce 上,然后在 onResume 上保存值,或者将值保存在 SavedInstance 上并继续使用 Restor
  • 你能给我举个例子吗?此外,Prmths 和 codeMagic 上面的两个人认为我应该修复我在 logcat 中收到的错误消息。你对此有何看法?
  • @amir0220 您只是在膨胀布局并将其视图添加到某个视图中,要么添加所有布局视图,要么删除其父视图
  • 我不确定你的意思。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-28
  • 1970-01-01
相关资源
最近更新 更多