7种:
- onCreate
- onRestart
- onStart
- onResume
- onPause
- onStop
- onDestroy
onCreate:生命周期的第一个方法,当我们打开一个activity时首先走这个方法。
我们可以做什么:初始化工作。比如加载界面(setContentView)、数据初始化(findviewbyid等等)
onStart :表示activity正在被启动。
特点:activity可见,未出现在前台。
理解:activity已经显示出来了,但是我们看不到。
onResume :表示activity已经可见,并且出现在前台,可以与用户进行交互.
例如:activity上有Button,此时我们就可以进行点击了。
与onStart的区别:
onStart 前台不可见,所以不可交互。 onResume 前台可见,所以可以交互。
onPause:表示activity正在停止,接着很快执行onStop
注意:极端情况下,跳转其他activity,并且快速的回到当前activity时,当前activity的生命周期:onPause->onResume
但是这个“快速回到”要很快,一般情况下都是onPause->onStop->onRestart->onStart->onResume
ps:这里不能做太耗时操作,可以做一些数据存储,动画停止 。
onStop:表示activity即将停止。
onRestart : 当前activity正在重新启动,一般是用户行为导致,比如用户切换Activity,或者摁home键回到桌面,当用户再次回到本activity时,当前activity 走 onRestart->onStart->onResume
onDestroy :activity即将被销毁 ,activity生命周期最后一个回调,这里可以做一些回收工作,资源释放。
这里就以如下两个activity进行解读:
MainActivity:里面七个生命周期回调,和一个按钮。
Main2Activity:七个生命周期回调
代码如下(以这两个activity来说下切换流程)
MainActivity:
public class MainActivity extends AppCompatActivity {
public static final String TAG = "tags";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, Main2Activity.class));
}
});
Log.i(TAG, "onCreate:");
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "onResume: ");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "onPause: ");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "onStop: ");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, "onRestart: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy: ");
}
}
Main2Activity
public class Main2Activity extends AppCompatActivity {
public static final String TAG = "tags";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
setContentView(R.layout.activity_main2);
Log.i(TAG, "Main2Activity onCreate:");
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "Main2Activity onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "Main2Activity onResume: ");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "Main2Activity onPause: ");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "Main2Activity onStop: ");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, "Main2Activity onRestart: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "Main2Activity onDestroy: ");
}
}
MainActivity 经历了:onCreate->onStart->onResume
(2)由mainactivity跳转到Main2Activity时:
MainActivity 经历了:onPause->onStop
ps:MainActivity走onPause时,新的Main2Activity会先走: Main2Activity onCreate -> Main2Activity onStart -> Main2Activity onResume 然后MainActivity 走 ->onStop
强调:
1、如果此时Main2Activity 已经设置了透明主题则mainActivity是不走onStop的,只走个onPause。从MainActivity跳转到Main2Activity 我们还是可以看见mainActivity,所以验证了onPause的可见不前台。
2、展示对话框不影响生命周期。
MainActivity 走onPause->onStop
此时MainActivity走了 onRestart->onStart->onResume
(5)启动mainActivity跳转到Main2Activity,再返回到 mainActivity
如上:
1对应启动mainActivity
2对应跳转到Main2Activity
3对应再返回到 mainActivity
(6)用户打开mainactivity在摁back键时
mainActivity走了 onPause->onStop->onDestroy
从整个生命周期来说onCreate和onDestroy 是配对的,分别代表着actiity的创建和销毁。并且只可能调用一次。
从activity是否可见来说onStart和onStop是配对的,随着用户的操作两个生命周期可能被多次执行。
从activity是否在前台来说onResume和onPause是配对的,随着用户的操作两个生命周期可能被多次执行。
问题1:onStart 和 onResume ,onPause 和onStop从描述上差不多对我们来说有什么实质不同?
从使用过程来讲,两对的确差不多,甚至我们可以只保留一对,比如只保留onStart ,onStop。既然如此为什么安卓系统还要提供看似重复的借口呢?根据上面的分析我们知道,这两对接口代表不同的意义。onStart 、onStop是从是否可见的角度来回调的(前者可见后者不可见)。
onResume 、onPause,是从是否前台的角度来回调的(前者前台,后者非前台)
问题2:假设当前activity为A,如果这时用户打开新的activityB,B的onResume 和A的onPause那个先执行
执行结果 A:onPause->B:onCreate->B:onStart->B:onResume->A:onStop
1:案例推导参考:上文4、(2)
2:activity的启动流程源码中找答案。(略,参看安卓开发艺术探索)
比如说当前activity处于竖屏状态,如果突然旋转屏幕由于系统配置发生改变,默认情况下activity就会被销毁重建。当然我们也可以阻止系统重新创建我们的activity。
栗子:默认情况下我们打开activity
onSaveInstanceState、onRestoreInstanceState是我又添加的两个activity回调方法先不管,我们可以看出,activity首先销毁,然后重新建立。
其实activity还有两个方法onSaveInstanceState,onRestoreInstanceState。用来异常状态下存储数据。
同时我们知道onSaveInstanceState、onRestoreInstanceState方法中系统还自动为我们做了一些恢复工作,当activity异常情况下重新创建时,系统默认为我们保存当前activity的视图结构。并在activity重新创建时为我们恢复这些工作。比如文本框中输入的数据,ListView滚动到的位置等,这些view相关的状态系统都会默认为我们存储,并恢复。但是哪些view系统能帮我们恢复哪些数据,就要看个view的源码了(和activity一样view有这两个方法回调)
有关保存和恢复view层次结构 采用了委托思想(参看安卓开发艺术)
异常情况下EditText 数据恢复举例:
写回调用于恢复我们自己想要存的数据
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.i(TAG, "onSaveInstanceState: ");
outState.putString("tom","异常下存数据 :tom");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.i(TAG, "onRestoreInstanceState: ");
Log.i(TAG, " "+savedInstanceState.get("tom"));
}
可以看到回调走了数据也恢复了,editText内的数据系统帮我们恢复了,我们自定义的数据也恢复了
ps:特别注意我们的EditText一定要在xml布局中设置id,否则数据不会重新恢复(亲测,原因参看EditText源码)
我们在onSaveInstanceState中存数据,在onRestoreInstanceState和onCreate中都可以接受,接收区别如下:
这种情况我们不好模拟,但是其数据存储和恢复过程和资源配置发生改变回调是完全一致的
这里介绍下activity的优先级高低:
当系统内存不足时,系统会按照上述优先级杀死目标activity所在进程。并通过,onSaveInstanceState、onRestoreInstanceState来存储恢复数据。
如果一个进程中没有四大组件在执行(空进程),这个进程很快就会被系统杀死。因此一些后台工作,不适合脱离四大组件而独自运行在后台中,这样很容易被杀死。比较好的方法是将后台工作放入Service中从而保证进程有一定优先级,这样不会轻易被系统杀死。
ps:安卓中的进程(优先级从高到低):前台>可见>服务进程 >后台进程 >空进程
上面介绍了异常情况下activity会重新创建,那么可以阻止activity重新创建吗?答案是有的给activity指定configChanges属性。(如下)
属性值 | 含义 |
---|---|
mcc | SIM卡唯一标识IMSI(国际移动用户识别码)中的国家代码,由三维数组组成,中国为460,此项标识mcc代码发生改变 |
mnc | SIM卡唯一标识IMSI(国际移动用户识别码)中的运营商代码,由两位数字组成,中国移动TD系统为00,中国联通为01中国电信为03,此项标识mnc代码发生改变 |
locale | 设备的本地位置发生改变,一般指切换了系统语言 |
touchscreen | 触摸屏发生了变化,这个可以忽略,正常情况下不会发生 |
keyboard | 键盘类型发生了变化 例如,用户插入了一个外置键盘。 |
keyboardHidden | 键盘的可访问性发生改变比如用户调出键盘 |
navigation | 系统导航方式发生改变,比如采用了轨迹球导航,很难发生,可以忽略 |
screenLayout | 屏幕布局发生改变,很可能用户激活了另外一个显示设备 |
fontScale | 系统字体缩放比例发生改变,比如用户选择了一个新字号 |
uiMode | 用户界面模式发生改变,比如是否开启了夜间模式(api 8新添加) |
orientation | 屏幕方向发生改变,这个最常用,比如旋转了手机屏幕 |
screenSize | 当屏幕的尺寸信息发生改变,当旋转设备屏幕时,屏幕尺寸会发生改变,这个选项比较特殊,他和编译选项有关,当编译选项中的minSdkVersion和targetSdkVersion均低于13时此选项不会导致activity重启,否则导致activity重启(api 13新添加) |
smallestScreenSize | 当设备的物理屏幕尺寸信息发生改变,这个属性值和屏幕的方向没关系,仅表示实际的物理屏幕发生改变时触发,比如用户切换到外设的显示设备,和screenSize一样,当编译选项中的minSdkVersion和targetSdkVersion均低于13时此选项不会导致activity重启,否则导致activity重启(api 13新添加) |
layoutDirection | 当布局方向发生改变,这个属性用的比较少正常情况下无法修改布局的layoutDirection(api 17新添加) |
ps:上面的属性值我们可以配置多个 只需使用 | 连接即可。
从上面的表格我们发现如果我们没有为Activity指定configChanges的特定属性值,当异常情况下activity是会重新创建的。 上面表格中的属性值很多但是我们常用的也就几个-> locale、orientation、keyboardHidden。需要注意的是screenSize,smallestScreenSize只和编译版本有关,和运行环境无关。
为activity添加onConfigurationChanged回调
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.i(TAG, "onConfigurationChanged: ");
}
我们发现activity旋转屏幕后并没有销毁重建而是走了onConfigurationChanged 方法。
有关屏幕横竖屏切换可以参考:https://blog.csdn.net/u010005281/article/details/79531474
本节未完:
本章只总结了activity的生命周期,activity的启动模式,intentFliter的匹配规则还没总结,剩余这两部分总结请参考:
Activity的生命周期和启动模式(二)
本文来自<安卓开发艺术探索>笔记总结