注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。

原文链接:http://developer.android.com/training/basics/activity-lifecycle/recreating.html


在应用被正常使用的情况下,会有一些场景发生并使得你的activity被销毁,比如:当用户按下了返回键,或者你的activity调用了finish()方法将自己销毁。当你的activity处于停止态且已经很久没有被使用的情况下,系统也会将它销毁。还有一种情况是处于前台的activity需要更多的资源,此时系统必须将一部分后台进程停止来释放出一些内存空间。

当你的activity因为用户按下了返回键或者自己调用了finish()将自己销毁时,该Activity的实例将不再存在,因为导致其被销毁的行为暗示了这个activity已经不再需要了。然后如果是由于系统资源紧张而被迫将Activity销毁(非正常的应用行为),那么虽然Activity的实例已经不再了,当用户回到这个Activity时,系统仍然会记得它其实是存在的。此时,系统会利用该Activity被销毁时所保存的描述其状态的数据集,来创建一个新的Activity实例。这些系统用来恢复之前状态的数据被称作为“实例状态(instance state)”,它实质上是一个存储于一个Bundle对象的键值对数据集合。

Caution:

每次用户旋转了屏幕后,你的activity都会被销毁和重新创建。这样做的原因是因为屏幕的旋转会导致屏幕参数的变化(长和宽互换),此时你的activity可能需要加载一些可选的资源(比如针对于横屏或竖屏下的布局)

默认的,系统使用Bundle实例状态来保存你的activity布局中每个View对象的信息(比如在EditText对象中输入的文字)。所以,如果你的activity实例被销毁和重新创建,布局的状态会恢复到之前的状态,且你不需要为此编写代码。然而,你的activity可能会有更多你希望存储的状态信息,比如一些用来追踪用户进度的成员变量。

Note:

为了让Android系统恢复activity中的view状态,每个View必须有一个独有的ID,这个ID由属性字段“android:id”提供。

为了存储更多关于activity状态的数据,你必须覆写onSaveInstanceState()回调函数。当用户离开你的activity时系统会调用该方法,并且传递给他一个Bundle对象,存储数据以防activity被意外地销毁了。之后如果系统必须重新创建这个activity实例,它会把相同的Bundle对象传递给onRestoreInstanceState()方法和onCreate()方法。

图1. 当系统要停止你的activity时,它会调用onSaveInstanceState()方法(1),所以你可以指定你先要存储的额外数据,当activity被重新创建时会用到它们。如果activity被销毁了同时这个activity实例需要重新创建,系统会将(1)中定义的数据传递给onCreate()方法(2),以及onRestoreInstanceState()方法(3)

一). 保存你的Activity状态

当你的activity将要停止,系统会调用onSaveInstanceState()方法这样你的activity会通过键值对的形式将状态信息保存起来。这个方法的默认实现会保存activity的view状态,比如一个EditText控件内的文本信息或者ListView当前滑动到的位置信息。

为了为你的activity保存额外的状态信息,你必须实现onSaveInstanceState()方法,并且将键值对添加到Bundle对象中。例如:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
... @Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel); // Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}

Caution:

必须调用父类的onSaveInstanceState(),这样默认的实现会保存View的状态

二). 恢复你的Activity状态

当你的Activity在之前被销毁后需要被重新创建时,你可以通过系统传递给Activity的Bundle对象来恢复之前的状态。onRestoreInstanceState()方法和onCreate()方法都会接受到相同的Bundle对象,其中包含了实例的状态信息。

因为不管是系统在创建一个新的实例还是重新创建一个旧的,onCreate()都会被系统调用,所以在你尝试读取Bundle之前,必须检查它是否是null。如果是null,那么系统会创建一个新的activity实例,而不是进行恢复。

下面就是你将如何在onCreate()中恢复状态的例子:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first // Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
}

除了在onCreate()恢复状态,你还可以选择实现onRestoreInstanceState(),这个方法在系统调用了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(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

Caution:

必须调用父类的onRestoreInstanceState(),这样默认的实现会恢复View的状态

如果想要学习关于在运行时由于重启事件导致activity被重新创建(如旋转了屏幕),可以阅读:Handling Runtime Changes

【Android Developers Training】 18. 重新创建一个Activity的更多相关文章

  1. 【Android Developers Training】 1. 创建一个Android项目工程

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  2. 【Android Developers Training】 95. 创建一个同步适配器

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  3. 【Android Developers Training】 15. 启动一个Activity

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  4. 【Android Developers Training】 21. 创建一个可变动的UI

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  5. 【Android Developers Training】 20. 创建一个Fragment

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  6. 【Android Developers Training】 94. 创建一个空内容提供器(Content Provider)

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  7. 【Android Developers Training】 93. 创建一个空验证器

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  8. 【Android Developers Training】 3. 构建一个简单UI

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  9. 【Android Developers Training】 106. 创建并检测地理围栏

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

随机推荐

  1. dubbo高级配置学习

    启动时检查 可以通过check="false"关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动. 关闭某个服务的启动时检查:(没有提供者时报错) < ...

  2. VS2010 使用 EF5 框架步骤

    1.安装 nuget , 在nuget里联机查找 EF 5.x DbContext Generator for C# 模版下载安装 2.nuget 控制台执行 Install-Package Enti ...

  3. 9、JcomboBox下拉框事件监听

    9.JcomboBox下拉框事件监听 JComboBox()的事件监听类ItemListener.其范例代码如下: import java.awt.*; import java.awt.event.* ...

  4. spring-线程池(1)

    多线程并发处理起来通常比较麻烦,如果你使用spring容器来管理业务bean,事情就好办了多了.spring封装了java的多线程的实现,你只需要关注于并发事物的流程以及一些并发负载量等特性,具体来说 ...

  5. 教育行业app开发新契机,在线教育要从B端出发

    近几年移动互联网教育风生水起,在运营模式上的开拓也各不相同,随着移动互联网进入下半场,好未来.新东方.猿题库.学霸君等,都在加速三四线地区布局,以及教育行业app开发和升级. 在移动互联网下半场,用户 ...

  6. 初码-Azure系列-文章目录

    系统迁移 初码-Azure系列-记一次MySQL数据库向Azure的迁移 初码-Azure系列-迁移PHP应用至Azure的一些实践记录和思考 初码-Azure系列-记一次从阿里云到Azure的迁移和 ...

  7. VR全景智慧城市,完美的将虚拟与现实结合

    很多人都粗浅的认为,VR虚拟智慧城市只是简单的将智慧城市和虚拟现实相结合的产物,这样的VR虚拟智慧城市看起来更像是个VR内容产品,而非城市建设成果.但是我们换个角度来思考的话,现在很多VR虚拟智慧城市 ...

  8. javascript痛点之二作用域链

    1.执行环境(执行上下文) 先看段代码 var a = 10; var b = 20; function cc(){ var c = 30; alert("b="+b); } cc ...

  9. python加载sqlite3报错:No module named _sqlite3

    环境为Ubuntu16.04 Apache2.4 Python2.7.13 django 1.8 今天部署apache+django,经过各种折腾,好不容易配置完了,发现错误Apache的日志里有一项 ...

  10. Oracle查询数据出来乱码问题?

    为什么Oracle 查询出来的数据会产生乱码?   安装的数据库和客户端编码编码不一致就会产生乱码,要想解决此问题改一下客户端的编码即可 1. select * from table; 如果是这种问题 ...