前提
首先我们要知道,在系统中有一个专门用来管理Activity实例对象的栈,这个堆栈采用的是“先进后出”的模式。我们每创建一个活动对象都会放进这个堆栈中,而最顶端的活动对象才是可见的并且可以和用户进行交互的!整个堆栈的活动过程如下图所示:
了解了堆栈之后,我们再看下官方最新的活动生命周期图:
其实我们平常在用APP的时候看到的APP界面就是以Activity(活动)为基础的,从而我们也能知道活动的最简单的功能就是可以给用户展示界面,并且和用户交互!从这个生命周期图中“visible”,“hidden”等字样我们也能看出这一现象!
那么我们在可以将活动的状态分为:
- 创建(初始化)
- 可见不可交互
- 可见可交互
- 部分可见不可交互
- 不可见不可交互
- 销毁
在结合上图,我们在分别说明一下图中的7个生命周期方法都有什么作用:
- onCreate() : 活动创建的时候被调用,创建之后之后活动被销毁了之后再次启动才会被调用。在这个方法中我们通常做一些初始化的工作,例如:控件的初始化,数据和控件的绑定等等!
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
- 拓展说明:从上图中可以看到方法还带有一个Bundle类型的参数,Bundle类型大家应该知道它可以以键值对的形式存放许多类型的数据,所以这个参数可以用来恢复一些数据,至于是什么数据,并且这些数据是怎么来的,后面会详情说明的!
-
onStart() :执行到这个方法的时候就是我们上面说的“可见不可交互”状态!
-
onResume():执行到这个方法的时候就是我们上面说的“可见可交互”状态,这个时候活动是处于栈顶的!
-
onPause():执行这个方法的时候,活动处于暂停状态,就是我们说的部分可见不可交互状态,比如:启动一个对话框模式的活动等,(特别注意:弹出的对话框并不能出发改方法)。从图中我们可以看到这个方法之后有两个路径,向前就是重新展示上一个活动,向后就是停止当前的活动!
-
onStop():这个方法代表活动不再可见,也就是此时活动处于后台运行状态!这个可以有两个选择,要么就是通过onRestart()方法重新打开活动,要么就是执行onDestroy()销毁活动!
-
onRestart():这个方法就是就是用来重新打开活动的,不知道这个方法有什么意义,官方给的解释就是:
当您的Activity从停止状态返回前台时,它会接收对 onRestart() 的调用。系统还会在每次您的Activity变为可见时调用 onStart() 方法(无论是正重新开始还是初次创建)。 但是,只会在Activity从停止状态继续时调用 onRestart() 方法,因此您可以使用它执行只有在Activity之前停止但未销毁的情况下可能必须执行的特殊恢复工作。
-
onDestroy():就是销毁活动的实例了,并且这个活动也将从活动栈的栈顶被清除!
梳理流程:
- 当我们启动活动的时候会执行: 此时活动可见可交互
- onCreate()
- onStart()
- onResume()
- 之后的操作分两种情况:
-
如果启动对话框模式的Activtiy或其他操作,使得当前活动部分不可见,则只会执行:
-
onPause()
-
这种情况之后的操作也分两种:
- onResume() 执行这个方法让活动重新处于前端
- onStop() 执行这个方法让活动重新处于后台
-
-
-
如果启动另一个活动,使得当前活动完全不可见了,则会执行:
-
onPause()
-
onStop()
-
这种情况之后的操作也分两种:
- onDestroy() 执行这个方法销毁活动
- onRestart(),onStart(),onResume() 执行这些方法让重新打开活动
-
-
需要了解的在生命周期中的一些方法:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
L.e("保存活动状态数据");
}
这个方法是一定是在onStop()方法之前执行在但是不一定在onPause()之后执行,时序不能得到保证。该的方法可以通过Bundle类型的参数来保存活动的状态数据。这里保存的数据,可以在onCreate方法中的参数获取到!上面已经说过了!也可以通过下面的方法获取到:
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
只要执行了这个方法就代表savedInstanceState参数里一定有数据,相反只有当savedInstanceState参数里有数据才会执行这个方法!但是onCreate方法却不一定,至于要在哪个方法里恢复数据,其实都可以!官方推荐是在onRestoreInstanceState这个方法中恢复数据;
上面这两个方法只会在活动异常终止的情况下执行,在正常通过返回键销毁活动的时候并没有执行该过程。
拓展知识:横竖屏切换
为什么会说这个呢,因为在手机进行横竖屏切换的时候,会引发活动生命周期的一轮变化,下面我通过打印的log进行说明:
首先看下代码:
在剩下的生命周期方法中我也打印了相关日志,还有代码中的参数,之后我启动程序看打印的日志:
图片.png执行了相关的周期方法,并且打印了参数值!这时候我手动旋转手机变成横向的再看打印的日志:
图片.png从日志可以看出,先是执行了onPause(),onStop(),onDestroy(),把当前的活动销毁,之后又重新执行了一遍生命周期!
解决这个问题也很简单,就是在manifests文件生命这个活动的资源里添加这条属性:
图片.png这两个值解释下:
orientation:屏幕方向发生变化,配置该参数可以解决横竖屏切换时,Activity重建问题(API<13)
screenSize:当设备旋转时,屏幕尺寸发生变化,API>13后必须配置该参数才可以保证横竖切换不会导致Activity重建。
这样切屏的时候就不再回调
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
而是回调:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
L.e("onConfigurationChanged");
}
并且不会再引发生命周期的变化:
QQ截图20170426150630.png** 并且可以通过一下方法来判断旋转之后的屏幕状态是横屏还是竖屏: **
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
L.e("此时为横屏模式");
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
L.e("此时为竖屏模式");
}
}
网友评论