请如何使用onSavedInstanceState示例


110

当涉及到保存状态时,我感到困惑。因此,我知道onSaveInstanceState(Bundle)活动即将被销毁时会调用它。但是,如何存储您的信息并将其恢复到原始状态onCreate(Bundle savedInstanceState)?我不知道该捆绑包将如何还原信息。如果有人可以提供示例,将很有帮助。开发人员指南无法很好地解释这一点。

public class Conversation extends Activity {
    private ProgressDialog progDialog;
    int typeBar;
    TextView text1;
    EditText edit;
    Button respond;
    private String name;
    private String textAtView;
    private String savedName;

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        setContentView(R.layout.dorothydialog);
        text1 = (TextView)findViewById(R.id.dialog);
        edit = (EditText)findViewById(R.id.repsond);
        respond = (Button)findViewById(R.id.button01);

        if(savedInstanceState != null){
            savedInstanceState.get(savedName);
            text1.setText(savedName);
        }
        else{
            text1.setText("Hello! What is your name?");
            respond.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    name = edit.getText().toString();
                    text1.setText("Nice to meet you "+ name);
                }   
            });
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
        outState.putString(savedName, name);
    }
}

text1.setText(savedInstanceState.getString(savedName));
Spidy

@Spidy onBackpressed呢?我对捆绑包会如何反应?
tj walker

你不会的 当用户按下后退按钮时。该活动被杀死。使用数据库进行永久数据存储。使用捆绑包将重新启动的应用程序恢复到之前的状态。
Spidy

Answers:


198

Bundle是你要保存的信息的容器。您可以使用put *函数将数据插入其中。这是可用于将数据存储在中的put函数的简短列表(还有更多)Bundle

putString
putBoolean
putByte
putChar
putFloat
putLong
putShort
putParcelable (used for objects but they must implement Parcelable)

在您的onCreate函数中,这Bundle将交还给程序。检查应用程序是否正在重新加载或首次启动的最佳方法是:

if (savedInstanceState != null) {
    // Then the application is being reloaded
}

要取出数据,请像使用put *函数一样使用get *函数。数据存储为名称-值对。这就像一个哈希图。您提供一个键和一个值,然后当您要返回值时,您给键,函数将获得该值。这是一个简短的例子。

@Override
public void onSaveInstanceState(Bundle outState) {
   outState.putString("message", "This is my message to be reloaded");
   super.onSaveInstanceState(outState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        String message = savedInstanceState.getString("message");
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }
}

您保存的消息将被烘烤到屏幕上。希望这可以帮助。


14
在您的活动暂停之前,将调用onSaveInstanceState()。因此,在可能被销毁后需要的所有信息都可以从已保存的捆绑包中获取
Diederik

@Spidy太棒了!您真的让我了解了有关捆绑的一切!所以我猜出outState传递回了savedInstanceState包?正确?
tj walker

是的 该outState包被传递回为savedInstanceState包
Spidy

1
@tj walker-另一个很棒的资源是技术参考书。Pro Android 3是一种便宜而广泛的资源,您可以在Amazon上获得
Spidy

@Spidy我在上面发布了我的活动代码供您查看。如您所建议的,也许您可​​以让我知道我是否保存了我的状态。
tj walker

34

所有新的Android开发人员都应该知道的一个主要注意事项是,只要您为其分配ID,小部件中的任何信息(TextView,Button等)都将由Android自动保留。因此,这意味着大多数UI状态都会得到妥善处理。仅当您需要存储其他数据时,这才成为问题。

Android文档

您唯一需要做的工作就是为每个要保存其状态的窗口小部件提供唯一的ID(带有android:id属性)。如果小部件没有ID,则无法保存其状态


1
那是真的吗?因为我有一个带有按钮的活动textview和编辑文本。如果应用程序被破坏或杀死,则所有内容将恢复为原始状态。在我的应用程序中,每当用户单击按钮时,textView文本都会更改。
tj walker

文件不正确吗?我从来没有一个视图保存自己的信息。我认为最好的办法是自己保存所有信息。
Spidy

2
如果您的目标是在SaveInstanceState上保存信息,则不适合这样做。那是因为不能保证会被调用(请参阅文档)。您应该改为写入数据库,SharedPreferences等。是的,此信息是准确的。测试UI是否以这种方式持久的最好方法是在方向更改时重新旋转onCreate并使用捆绑包还原状态,以旋转显示。
基思·阿德勒

@Nissan Fan,您能像上面的间谍一样举一个例子吗?与sharedprefs和所有?谢谢
tj walker

坦率地说,最好的例子来自文档。 developer.android.com/guide/topics/data/data-storage.html#pref
Keith Adler

6

很好的信息:您无需在onCreate()方法中检查Bundle对象是否为null。使用onRestoreInstanceState()方法,系统在onStart()方法之后调用该方法。仅当存在要还原的保存状态时,系统才调用onRestoreInstanceState(),因此您无需检查Bundle是否为null


5

储存信息:

static final String PLAYER_SCORE = "playerScore";
static final String PLAYER_LEVEL = "playerLevel";

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

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

如果您不想在onCreate-Method中还原信息:

下面是示例:重新创建活动

您可以选择实现onRestoreInstanceState(),而不是在onCreate()期间恢复状态,系统在onStart()方法之后调用该方法。仅当存在要还原的保存状态时,系统才调用onRestoreInstanceState(),因此您无需检查Bundle是否为null

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

// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(PLAYER_SCORE);
mCurrentLevel = savedInstanceState.getInt(PLAYER_LEVEL);
}

0

基本上onSaveInstanceState(Bundle outBundle)会给你一个捆绑包。当您查看Bundle类时,您会发现可以在其中放入许多不同的东西。在下一次调用onCreate()时,只需将Bundle作为参数返回。然后,您可以再次读取值并恢复活动。

假设您有一个带有EditText的活动。用户在其中写了一些文本。之后,系统调用您的onSaveInstanceState()。您从EditText中读取文本,然后通过Bundle.putString(“ edit_text_value”,theValue)将其写入Bundle。

现在onCreate被调用。您检查提供的包是否不为空。如果是这样,您可以通过Bundle.getString(“ edit_text_value”)恢复值并将其放回EditText中。


0

这是额外的信息。

想象一下这种情况

  1. ActivityA启动ActivityB。
  2. ActivityB通过发布新的ActivityAPrime

    Intent intent = new Intent(getApplicationContext(), ActivityA.class);
    startActivity(intent);
    
  3. ActivityAPrime与ActivityA没有关系。
    在这种情况下,ActivityAPrime.onCreate()中的Bundle将为null。

如果ActivityA和ActivityAPrime应该是相同的活动,而不是不同的活动,则ActivityB应该调用finish()而不是使用startActivity()。


在您的示例中,只是为了澄清是ActivityA == ActivityA实例1和ActivityAPrime == ActivityA实例2?另外,当您说“ ActivityB应该比使用startActivity()时调用finish()”。您的意思是:(1)AcitivityB应该先调用finish()然后再使用startActivity()(2)还是ActivityB应该调用finish()而不是完全不使用startActivity()?如果您指的是选项2,您将如何建议某人重新启动相同的活动实例1,以便您可以在活动被销毁/完成之前加载活动中包含的数据?谢谢
cjayem13

ActivityA和ActivityAPrime属于同一类,但实例不同。在这种情况下,ActivityA尚未完成其业务,在其中间,它创建并启动了ActivityB,因此,当ActivityB完成时,ActivityA应继续其剩余业务。在这种情况下,调用startActivity并期望ActivityA和ActiviyAPrime是同一实例是错误的。因此我们不应该重新启动ActivityA,只需完成ActivityB并让ActivityA恢复运行即可…
ken 2014年

0

如果未从中加载数据,请savedInstanceState使用以下代码。
问题是url调用未完全完成,因此,请检查是否已加载数据,然后显示instanceState值。

//suppose data is not Loaded to savedInstanceState at 1st swipe
if (savedInstanceState == null && !mAlreadyLoaded){
    mAlreadyLoaded = true;
    GetStoryData();//Url Call
} else {
    if (listArray != null) {  //Data Array From JsonArray(ListArray)
        System.out.println("LocalData  " + listArray);
        view.findViewById(R.id.progressBar).setVisibility(View.GONE);
    }else{
        GetStoryData();//Url Call
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.