而 onSaveInstanceState(Bundle outState) 什么时候调用呢?查阅了大量的资料,并经过测试发现,以下几种情形会被调用:
1.当点击 home 键回到主页或者长按 home 键选择其他应用程序时调用;
2.按下电源键锁屏的时候会调用;
3.启动一个新的 Activity 时调用;
4.横竖屏切换的时候,调用,这个很好理解,因为你横竖屏切换的时候,其实是销毁了当前 Activity 然后再创建 。
而 onRestoreInstanceState() 一般都是在 onStart() 和 onResume() 之间调用。
比如综合上述 onSaveInstanceState() 的存数据的时机也可以想象,并不一定只有在Activity 销毁时才会去存,但是无论是哪种情况,当再次返回应用或者再次返回Activity 时,肯定调用了 onStart() 和 onResume(),所以我们也就能理解为什么 onRestoreInstanceState() 在这两个生命周期之间调用了。
onRestoreInstanceState() 和 onCreate() 的区别是 :
onRestoreInstanceState() 一旦被调用,其参数 Bundle savedInstanceState 一定是有值的,我们不用额外第判断是否为空;但是 onCreate() 不行,onCreate() 如果是正常启动,其参数 Bundle savedInstanceState 肯定为null,所以我们必须要额外判断。
这两个方法,官方推荐采用 onRestoreInstanceState() 去恢复数据。
讲了一堆概念性的东西,国际惯例,上代码。
package com.mesmerize.activitystate;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("MainActivity.onCreate");
if (savedInstanceState != null) {
String test_result = savedInstanceState.getString("test_result");
System.out.println("[MainActivity.onCreate] :: test_result = " + test_result);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
System.out.println("MainActivity.onSaveInstanceState");
outState.putString("test_result","且随疾风前行,身后一许流星.");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String test_result = savedInstanceState.getString("test_result");
System.out.println("[MainActivity.onRestoreInstanceState] :: test_result = " + test_result);
}
@Override
protected void onStart() {
super.onStart();
System.out.println("MainActivity.onStart");
}
@Override
protected void onPause() {
super.onPause();
System.out.println("MainActivity.onPause");
}
@Override
protected void onStop() {
super.onStop();
System.out.println("MainActivity.onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
System.out.println("MainActivity.onDestroy");
}
}
代码很简单,就是给大家看看调用顺序,用于验证上述结论。
最简单的其实最有力道,工作后你就发现,理解了调用顺序,调换一下代码的执行顺序就能解决你2,300行代码解决不了的事情。
看现象,当我启动应用的时候:
com.mesmerize.activitystate I/System.out: MainActivity.onCreate
com.mesmerize.activitystate I/System.out: MainActivity.onStart
为了最直观有效,我只验证横竖屏切换的结果了,其他的结果,有兴趣可以自己验证,我就不在大篇幅的累述。当我切换横屏时:
com.mesmerize.activitystate I/System.out: MainActivity.onPause
com.mesmerize.activitystate I/System.out: MainActivity.onSaveInstanceState
com.mesmerize.activitystate I/System.out: MainActivity.onStop
com.mesmerize.activitystate I/System.out: MainActivity.onDestroy
com.mesmerize.activitystate I/System.out: MainActivity.onCreate
com.mesmerize.activitystate I/System.out: [MainActivity.onCreate] :: test_result = 且随疾风前行,身后一许流星.
com.mesmerize.activitystate I/System.out: MainActivity.onStart
com.mesmerize.activitystate I/System.out: [MainActivity.onRestoreInstanceState] :: test_result = 且随疾风前行,身后一许流星.
可以看到,onPause() 之后 onSaveInstanceState() 就执行了,在这里我存了一个 String 。而后Activity 重新创建,走了 onCreate() 并判断 saveInstanceState 参数不为 null,取出数据“且随疾风前行,身后一许流星。”然后走了onStart()和onRestoreInstanceState 并取出相同的数据“且随疾风前行,身后一许流星。”
以上演示了一个简单的存取字符串,其实它还能存更多更多类型的数据,比如Bundle、比如Byte、比如Char、比如Parcelable等等等等。
standard
singleTop
singleTask
singleInstance
<activity
android:name="全类名"
android:launchMode="singleTask"/>
Intent intent = new Intent(this,目标Activity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
这两种方式都可以为 Activity 指定启动模式,但是二者还是有区别的。首先,优先级不同,第二种方式的优先级要高于第一种,当两种同时存在时,以第二种方式为准;
Activity 的 Flags 有很多,作用也很多,有的标记为可以设定 Activity 的启动模式,比如
FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_SINGLE_TOP 等;
还有的标记位可以影响 Activity 的运行状态,比如
FLAG_ACTIVITY_CLEAR_TOP 和 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 等。
FLAG_ACTIVITY_NEW_TASK
这个标记位的作用是为 Activity 指定“singleTask”启动模式,其效果和在 XML 中指定该启动模式相同。
FLAG_ACTIVITY_SINGLE_TOP
这个标记位的作用是为 Activity 指定“singleTop”启动模式,其效果和在 XML 中指定该启动模式相同。
FLAG_ACTIVITY_CLEAR_TOP
具有此标记位的 Activity,当它启动时,在同一个任务栈中所有位于它上面的 Activity 都要出栈。这个标记位一般会和 singleTask 启动模式一起出现,在这种情况下,被启动 Activity 的实例如果已经存在,那么系统就会调用它的 onNewIntent。如果被启动的 Activity 采用 standard 模式启动,那么它连同它之上的 Activity 都要出栈,系统会创建新的 Activity 实例并放入栈顶。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有此标记的 Activity 不会出现在历史 Activity 的列表中,当某些情况下我们不希望用户通过历史列表回到我们的 Activity 的时候这个标记比较有用。它等同于在 XML 中指定 Activity 的属性 android:excludeFromRecents="true"。
FLAG_ACTIVITY_NO_HISTORY
使用这种模式启动 Activity,当该 Activity 启动其他 Activity 后,该 Activity 就消失了,不会保留在 Activity 栈中,例如 A-B,B中以这种模式启动 C,C 再启动 D,则当前 Activity 栈为 ABD。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |