我一直在安卓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");
    }

其他回答

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

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

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

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

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

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

您需要重写onSaveInstanceState(Bundle savedInstanceState),并将要更改的应用程序状态值写入Bundle参数,如下所示:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
  super.onSaveInstanceState(savedInstanceState);
  // Save UI state changes to the savedInstanceState.
  // This bundle will be passed to onCreate if the process is
  // killed and restarted.
  savedInstanceState.putBoolean("MyBoolean", true);
  savedInstanceState.putDouble("myDouble", 1.9);
  savedInstanceState.putInt("MyInt", 1);
  savedInstanceState.putString("MyString", "Welcome back to Android");
  // etc.
}

Bundle本质上是一种存储NVP(“名称-值对”)映射的方法,它将被传递到onCreate()和onRestoreInstanceState(),然后在那里您可以从如下活动中提取值:

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  // Restore UI state from the savedInstanceState.
  // This bundle has also been passed to onCreate.
  boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
  double myDouble = savedInstanceState.getDouble("myDouble");
  int myInt = savedInstanceState.getInt("MyInt");
  String myString = savedInstanceState.getString("MyString");
}

或者从碎片中提取。

@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
    super.onViewStateRestored(savedInstanceState);
    // Restore UI state from the savedInstanceState.
    // This bundle has also been passed to onCreate.
    boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
    double myDouble = savedInstanceState.getDouble("myDouble");
    int myInt = savedInstanceState.getInt("MyInt");
    String myString = savedInstanceState.getString("MyString");
}

您通常会使用此技术来存储应用程序的实例值(选择、未保存的文本等)。

我的同事写了一篇文章,解释了Android设备上的应用程序状态,包括活动生命周期和状态信息的解释,如何存储状态信息,以及保存到状态Bundle和SharedPreferences。看看这里。

本文涵盖三种方法:

使用实例状态包存储应用程序生存期(即临时)的本地变量/UI控制数据

[Code sample – Store state in state bundle]
@Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
  // Store UI state to the savedInstanceState.
  // This bundle will be passed to onCreate on next call.  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  savedInstanceState.putString(“Name”, strName);
  savedInstanceState.putString(“Email”, strEmail);
  savedInstanceState.putBoolean(“TandC”, blnTandC);

  super.onSaveInstanceState(savedInstanceState);
}

使用共享首选项在应用程序实例之间(即永久)存储本地变量/UI控制数据

[Code sample – store state in SharedPreferences]
@Override
protected void onPause()
{
  super.onPause();

  // Store values between instances here
  SharedPreferences preferences = getPreferences(MODE_PRIVATE);
  SharedPreferences.Editor editor = preferences.edit();  // Put the values from the UI
  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  editor.putString(“Name”, strName); // value to store
  editor.putString(“Email”, strEmail); // value to store
  editor.putBoolean(“TandC”, blnTandC); // value to store
  // Commit to storage
  editor.commit();
}

使用保留的非配置实例在应用程序生存期内的活动之间保持对象实例在内存中的活动状态

[Code sample – store object instance]
private cMyClassType moInstanceOfAClass; // Store the instance of an object
@Override
public Object onRetainNonConfigurationInstance()
{
  if (moInstanceOfAClass != null) // Check that the object exists
      return(moInstanceOfAClass);
  return super.onRetainNonConfigurationInstance();
}

哪些要保存,哪些不保存?

有没有想过,当方向改变时,为什么EditText中的文本会自动保存?这个答案是给你的。

当“活动”的实例被破坏并且系统重新创建新实例时(例如,配置更改)。它尝试使用一组保存的旧活动状态(实例状态)数据重新创建它。

实例状态是存储在Bundle对象中的键值对的集合。

例如,默认情况下,系统将视图对象保存在捆绑包中。

EditText中的文本在ListView中滚动位置等。

如果需要将另一个变量保存为实例状态的一部分,则应使用OVERRIDE onSavedInstanceState(Bundle savedinstaneState)方法。

例如,GameActivity中的int currentScore

有关保存数据时onSavedInstanceState(Bundle savedinstaneState)的详细信息

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

所以如果你忘了打电话super.onSaveInstanceState(savedInstanceState);默认行为无法工作,即EditText中的文本无法保存。

要选择哪一项来恢复“活动”状态?

 onCreate(Bundle savedInstanceState)

OR

onRestoreInstanceState(Bundle savedInstanceState)

这两种方法都获得相同的Bundle对象,因此在哪里编写恢复逻辑并不重要。唯一的区别是,在onCreate(Bundle savedInstanceState)方法中,您必须给出一个空检查,而在后一种情况下不需要它。其他答案已经有了代码片段。你可以参考他们。

有关onRestoreInstanceState(Bundle savedinstaneState)的详细信息

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from the saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
}

始终调用super.onRestoreInstanceState(savedInstanceState);以便系统默认还原视图层次结构

奖金

只有当用户打算返回“活动”时,系统才会调用onSaveInstanceState(Bundle savedInstanceState)。例如,您正在使用App X,突然接到一个电话。移动到调用方应用程序并返回到应用程序X。在这种情况下,将调用onSaveInstanceState(Bundle savedInstanceState)方法。

但如果用户按下后退按钮,请考虑这一点。假设用户不打算返回“活动”,因此在这种情况下,系统不会调用onSaveInstanceState(Bundle savedInstanceState)。重要的是,在保存数据时,您应该考虑所有情况。

相关链接:

演示默认行为Android官方文档。

现在Android为保存状态提供了ViewModels,您应该尝试使用它而不是saveInstanceState。