演练 - 保存活动状态
我们已在活动生命周期指南中介绍了保存状态背后的理论:现在,让我们演练一个示例。
活动状态演练
让我们打开 ActivityLifecycle_Start 项目,生成并运行它。 这是一个非常简单的项目,通过两个活动来演示活动生命周期以及如何调用各种生命周期方法。 启动应用程序时,将显示屏幕 MainActivity
:
查看状态转换
此示例中的每个方法都会写入 IDE 应用程序输出窗口以指示活动状态。 (要在 Visual Studio 中打开输出窗口,请键入 Ctrl-Alt-O;要在 Visual Studio for Mac 中打开输出窗口,请单击“查看”>“填充”>“应用程序输出”。)
应用首次启动时,输出窗口将显示活动 A 的状态更改:
[ActivityLifecycle.MainActivity] Activity A - OnCreate
[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume
单击“启动活动 B”按钮时,可以看到活动 A 会在活动 B 经历其状态更改时暂停和停止:
[ActivityLifecycle.MainActivity] Activity A - OnPause
[ActivityLifecycle.SecondActivity] Activity B - OnCreate
[ActivityLifecycle.SecondActivity] Activity B - OnStart
[ActivityLifecycle.SecondActivity] Activity B - OnResume
[ActivityLifecycle.MainActivity] Activity A - OnStop
因此,活动 B 会代替活动 A 启动并显示:
单击“后退”按钮时,活动 B 将被销毁并恢复活动 A:
[ActivityLifecycle.SecondActivity] Activity B - OnPause
[ActivityLifecycle.MainActivity] Activity A - OnRestart
[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume
[ActivityLifecycle.SecondActivity] Activity B - OnStop
[ActivityLifecycle.SecondActivity] Activity B - OnDestroy
添加单击计数器
接下来,我们将更改应用程序,以便设置一个在单击它时进行计数并显示单击次数的按钮。 首先,我们将 _counter
实例变量添加到 MainActivity
:
int _counter = 0;
接下来,我们编辑 Resource/layout/Main.axml 布局文件,并添加一个新的 clickButton
,以显示用户单击该按钮的次数。 生成的 Main.axml 的外观应如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/mybutton_text" />
<Button
android:id="@+id/clickButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/counterbutton_text" />
</LinearLayout>
我们将以下代码添加到 MainActivity
中 OnCreate 方法的末尾 - 此代码可处理来自 clickButton
的单击事件:
var clickbutton = FindViewById<Button> (Resource.Id.clickButton);
clickbutton.Text = Resources.GetString (
Resource.String.counterbutton_text, _counter);
clickbutton.Click += (object sender, System.EventArgs e) =>
{
_counter++;
clickbutton.Text = Resources.GetString (
Resource.String.counterbutton_text, _counter);
} ;
再次生成并运行应用时,将显示一个新按钮,该按钮会在每次单击时递增并显示 _counter
的值:
但当我们将设备旋转到横向模式时,将会丢失此计数:
通过检查应用程序输出,我们会看到活动 A 在从纵向到横向模式的旋转过程中依次经历暂停、停止、销毁、重新创建、重启和恢复:
[ActivityLifecycle.MainActivity] Activity A - OnPause
[ActivityLifecycle.MainActivity] Activity A - OnStop
[ActivityLifecycle.MainActivity] Activity A - On Destroy
[ActivityLifecycle.MainActivity] Activity A - OnCreate
[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume
由于活动 A 在旋转设备时被销毁并重新创建,因此其实例状态会丢失。 接下来,我们将添加代码以保存和还原实例状态。
添加代码以保留实例状态
我们将向 MainActivity
添加一个方法来保存实例状态。 在销毁活动 A 之前,Android 会自动调用 OnSaveInstanceState,并传入可用于存储实例状态的捆绑包。 我们使用它将单击计数保存为整数值:
protected override void OnSaveInstanceState (Bundle outState)
{
outState.PutInt ("click_count", _counter);
Log.Debug(GetType().FullName, "Activity A - Saving instance state");
// always call the base implementation!
base.OnSaveInstanceState (outState);
}
在重新创建和恢复活动 A 时,Android 会将此 Bundle
传回 OnCreate
方法。 让我们向 OnCreate
添加代码以从传入的 Bundle
还原 _counter
值。 在定义 clickbutton
行之前添加以下代码:
if (bundle != null)
{
_counter = bundle.GetInt ("click_count", 0);
Log.Debug(GetType().FullName, "Activity A - Recovered instance state");
}
再次生成并运行应用,然后单击第二个按钮几次。 将设备旋转到横向模式时,将会保留计数!
我们观察一下输出窗口,看看发生了什么:
[ActivityLifecycle.MainActivity] Activity A - OnPause
[ActivityLifecycle.MainActivity] Activity A - Saving instance state
[ActivityLifecycle.MainActivity] Activity A - OnStop
[ActivityLifecycle.MainActivity] Activity A - On Destroy
[ActivityLifecycle.MainActivity] Activity A - OnCreate
[ActivityLifecycle.MainActivity] Activity A - Recovered instance state
[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume
在调用 OnStop 方法之前,调用了新的 OnSaveInstanceState
方法以将 _counter
值保存在 Bundle
中。 Android 在调用 OnCreate
方法时已将其此 Bundle
传递回我们,并且我们能够使用它将 _counter
值还原为我们离开时的位置。
总结
在此演练中,我们已使用活动生命周期的知识来保留状态数据。