Android onSaveInstanceState onRestoreInstanceState
在本教程中,我们将讨论两种管理应用程序状态的重要方法,即onSaveInstanceState和onRestoreInstanceState。
我们将开发一个Counter Android应用程序,当配置更改时,我们将其中处理应用程序的状态。
Android生命周期
以下是我们应用程序中活动的生命周期:
每当进行配置更改(例如轮换或者应用程序进入多窗口模式)时,都会重新创建活动。
在这种娱乐中,应用程序将重新启动,如果处理不当,可能会丢失视图中的数据。
为此,有两种方法在生命周期的不同阶段触发:
- onSaveInstanceState
- onRestoreInstanceState
它们用于保存和检索值。
这些值以键值对的形式存储。
让我们分别看看它们。
onSaveInstanceState
通常在调用onStop()之前/之后调用onSaveInstanceState方法。
视Android版本而异。
在旧版本中,它通常是在onStop()之前获得的。
在此方法内部,我们以键值对的形式将重要值保存在Bundle中。
onSaveInstanceState方法如下所示:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
在outState捆绑实例上,我们添加键值对。
以下是适用的方法:
我们可以通过将类设置为Parcelable或者Serializable来传递自定义类实例。
让我们看一个使用Parcelable的示例,因为它比Serializable更快。
以下是一个自定义类:
public class Model implements Parcelable {
public long id;
public String name;
public Model(long id, String name) {
this.id = id;
this.name = name;
}
protected Model(Parcel in) {
id = in.readLong();
name = in.readString();
}
public final Creator<Model> CREATOR = new Creator<Model>() {
@Override
public Model createFromParcel(Parcel in) {
return new Model(in);
}
@Override
public Model[] newArray(int size) {
return new Model[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(id);
parcel.writeString(name);
}
}
writeToParcel方法是我们在Parcelable实例上设置类属性的地方。
现在创建模型的实例并将其保存在onSaveInstanceState中。
Model model = new Model(10, "Hello");
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("parcelable", model);
}
现在我们可以在onRestoreInstanceState方法中检索这些保存的值。
注意:每当您在应用程序中按下主屏幕按钮时,也会调用onSaveInstanceState。
另一个注意事项:只要您在视图上设置了ID,诸如EditText之类的内容就可以隐式保存和恢复其内容。
活动将自动从"视图"层次结构中的每个单个"视图"收集"视图的状态"。
onRestoreInstanceState
仅当在onSaveInstanceState方法中保存了某些内容时,才会触发此方法。
它在onStart()之后被调用。
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Model model = savedInstanceState.getParcelable("parcelable");
}
以下是可用的其他方法:
超级方法实现可还原视图层次结构。
通常," onRestoreInstanceState"现在不经常用于恢复值。
可以通过onCreate方法中的Bundle完成相同的操作。
另外,由于始终会先调用onCreate方法,因此,仅在此处还原保存的实例是一种好习惯。
在下一节中,我们将创建一个计数器应用程序,其中使用上述方法保存计数器的状态。
代码
下面给出了" activity_main.xml"的代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:id="@+id/inName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Username"
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Phone number"
android:inputType="phone"
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textSize="32sp"
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="COUNT UP"
</LinearLayout>
在以上布局中,第二个EditText没有设置任何ID。
因此,当设备旋转或者发生任何导致活动重新创建的配置时,此EditText内容将被重置。
MainActivity.java的代码如下:
package com.theitroad.androidsaverestoreinstance;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Button button;
TextView textView;
int counter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
String message = savedInstanceState.getString("message");
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
counter = savedInstanceState.getInt("counter", 0);
}
button = findViewById(R.id.button);
textView = findViewById(R.id.textView);
textView.setText(String.valueOf(counter));
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
counter = Integer.valueOf(textView.getText().toString()) + 1;
textView.setText(String.valueOf(counter));
}
});
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("message", "This is a saved message");
outState.putInt("counter", counter);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Toast.makeText(getApplicationContext(), "onRestoreInstanceState", Toast.LENGTH_SHORT).show();
counter = savedInstanceState.getInt("counter", 0);
}
}
在这种情况下,保存计数器的整数值,然后在重新创建活动时,再次调用onCreate。
在那边,我们检查saveInstanceStateState Bundle是否为null。
如果不是,我们将使用计数器中的数据还原视图。
请注意,更改方向后,"电话号码"字段为空。

