我一直在安卓SDK平台上工作,现在还不清楚如何保存应用程序的状态。因此,考虑到“你好,Android”示例的这个小的重新设计:

package com.android.hello;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {

  private TextView mTextView = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mTextView = new TextView(this);

    if (savedInstanceState == null) {
       mTextView.setText("Welcome to HelloAndroid!");
    } else {
       mTextView.setText("Welcome back.");
    }

    setContentView(mTextView);
  }
}

我认为这对于最简单的情况来说已经足够了,但无论我如何离开应用程序,它总是以第一条消息来响应。

我确信解决方案就像重写onPause之类的东西一样简单,但我已经在文档中翻了大约30分钟,没有发现任何明显的东西。


当前回答

创建活动时,将调用其onCreate()方法。

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

savedInstanceState是Bundle类的一个对象,它第一次为空,但在重新创建时包含值。要保存“活动”的状态,必须重写onSaveInstanceState()。

   @Override
    protected void onSaveInstanceState(Bundle outState) {
      outState.putString("key","Welcome Back")
        super.onSaveInstanceState(outState);       //save state
    }

将值放在“outState”Bundle对象中,如outState.putString(“key”,“Welcome Back”),并通过调用super保存。当活动将被销毁时,它的状态将保存在Bundle对象中,并且可以在onCreate()或onRestoreInstanceState()中重新创建后恢复。在onCreate()和onRestoreInstanceState()中接收的捆绑包相同。

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

          //restore activity's state
         if(savedInstanceState!=null){
          String reStoredString=savedInstanceState.getString("key");
            }
    }

or

  //restores activity's saved state
 @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
      String restoredMessage=savedInstanceState.getString("key");
    }

其他回答

这是Android开发的经典“陷阱”。这里有两个问题:

有一个微妙的Android框架错误,它在开发过程中使应用程序堆栈管理变得非常复杂,至少在旧版本上如此(不完全确定是否/何时/如何修复)。我将在下面讨论这个bug。管理此问题的“正常”或预期方式本身就相当复杂,因为onPause/onResume和onSaveInstanceState/onRestoreInstanceState具有双重性

浏览所有这些线程,我怀疑很多时候开发人员都在同时讨论这两个不同的问题。。。因此,所有的困惑和“这对我不起作用”的报道。

首先,要澄清“预期”行为:onSaveInstance和onRestoreInstance是脆弱的,仅适用于暂时状态。预期用途(据我所知)是在手机旋转(方向改变)时处理“活动”娱乐。换言之,当您的“活动”在逻辑上仍处于“顶部”,但仍必须由系统重新实例化时,即为预期用途。保存的Bundle不会在进程/内存/GC之外持久化,因此如果您的活动进入后台,您就不能真正依赖它。是的,也许你的“活动”的内存可以保存到后台并逃脱GC,但这并不可靠(也不可预测)。

因此,如果您有一个场景,其中在应用程序的“启动”之间应该保持有意义的“用户进度”或状态,则指南是使用onPause和onResume。你必须自己选择并准备一个持久性商店。

但是,有一个非常令人困惑的错误,它使所有这一切变得复杂。详情如下:

当从Eclipse启动应用程序时,活动堆栈在第一次运行期间的行为不正确(#369007463)市场/浏览器应用程序安装程序允许第二个实例脱离应用程序(#36911210)

基本上,如果您的应用程序使用SingleTask标志启动,然后稍后从主屏幕或启动程序菜单启动它,那么随后的调用将创建一个新任务。。。你的应用程序将有两个不同的实例驻留在同一堆栈中。。。这变得非常奇怪,非常快。这似乎发生在开发期间启动应用程序时(即从Eclipse或IntelliJ),因此开发人员经常遇到这种情况。但也通过一些应用商店更新机制(因此它也会影响用户)。

我在这些线程中挣扎了几个小时,才意识到我的主要问题是这个bug,而不是预期的框架行为。一个很好的总结和解决方法(更新:见下文)似乎来自用户@kaciula的回答:

主页键按下行为

2013年6月更新:几个月后,我终于找到了“正确”的解决方案。您不需要自己管理任何有状态的startedApp标志。您可以从框架中检测到这一点并适当地保释。我在启动程序活动开始时使用此选项。创建:

if (!isTaskRoot()) {
    Intent intent = getIntent();
    String action = intent.getAction();
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && action != null && action.equals(Intent.ACTION_MAIN)) {
        finish();
        return;
    }
}

要获取存储在onCreate()中的活动状态数据,首先必须通过重写SaveInstanceState(Bundle savedInstanceState)方法将数据保存在savedInstanceStatus中。

当调用activity destroy SaveInstanceState(Bundle savedInstanceState)方法并保存要保存的数据时。当活动重新启动时,在onCreate()中也会得到同样的结果。(savedInstanceState不会为空,因为在活动被破坏之前,您已经在其中保存了一些数据)

savedInstanceState仅用于保存与“活动”的当前实例相关联的状态,例如当前导航或选择信息,这样,如果Android破坏并重新创建“活动”,它就可以恢复原样。请参阅onCreate和onSaveInstanceState的文档

对于更长寿命的状态,请考虑使用SQLite数据库、文件或首选项。请参阅保存持久状态。

现在,您可以使用实时数据和生命周期感知组件

https://developer.android.com/topic/libraries/architecture/lifecycle

请注意,根据Activity上的文档,对持久数据使用onSaveInstanceState和onRestoreInstanceState是不安全的。

文档说明(在“活动生命周期”部分):

请注意,保存改为onPause()中的持久数据的onSaveInstanceState(捆绑包)因为后者不是生命周期回调,因此不会在描述的每种情况下调用在其文档中。

换句话说,将持久数据的保存/恢复代码放在onPause()和onResume()中!

为了进一步澄清,这里有onSaveInstanceState()文档:

在活动被终止之前调用此方法,以便在未来的某个时候,它可以恢复其状态。对于例如,如果活动B在活动A之前启动点活动A被杀死以回收资源,活动A将具有通过此选项保存用户界面的当前状态方法,以便当用户返回活动A时用户界面可以通过onCreate(Bundle)或onRestoreInstanceState(捆绑包)。