生命周期
正常情况下的生命周期
也就是Activity从正常启动到最终销毁的生命周期。
- onCreate():Activity正在被创建。这里可以做一些初始化工作,例如加载布局、初始化数据等。
- onRestart():Activity正在重新启动。当Activity从不可见变成可见时(当前Activity按Home键返回桌面或打开了一个新的Activity后又回到这个Activity时,如果它的实例还未被销毁),这个方法就会被调用。
- onStart():Activity正在启动。此时Activity已经可见了,但它还在后台,无法和用户交互。
- onResume():Activity已经可见了,并且已经在前台并开始活动。
- onPause():Activity正在停止。紧接着onStop会被调用。这里可以做一些存储数据、停止动画等操作,但不能太耗时,因为旧Activity的onPause方法执行完后新Activity的onResume才会执行。
- onStop():Activity即将停止。可以做一些稍微重量级的回收工作,同样不能太耗时。
- onDestroy():Activity即将被销毁。同样可以做一些回收工作。
onPause()和onStop()的区别:
onPause可以理解为当前Activity失去焦点,而onStop表示当前Activity不可见。如果启动的新活动是一个对话框式的活动(透明主题),那么onPause会被调用,但是onStop不会。
具体场景
- Activity第一次启动 / Activity被系统回收后再次打开 的生命周期回调:onCreate→onStart→onResume
- Activity A启动Activity B,以及B回退到A,两者的生命周期变化
A启动B:
B回退到A:
上面A启动B时A的onStop方法在B启动后执行的原因:更快的启动新的活动,提高用户体验;下面B回退到A时onStop和onDestroy在A重启后执行也是同样的道理。
- 启动新的Activity或切换到桌面时:onPause→onStop。
特殊情况:新的Activity采用了透明主题,则当前Activity不会回调onStop。 - 再次回到原Activity:onRestart→onStart→onResume
- onCreate和onDestroy只会在Activity的整个生命周期调用一次;从Activity是否可见出发,onStart和onPause是配对的,可能被调用多次;从Activity是否在前台来说,onResume和onStop是配对的,可能被多次调用。
异常情况下的生命周期
异常情况指的是:
- 系统配置发生改变导致Activity被杀掉并重新创建
例如旋转屏幕导致系统配置发生改变,默认情况下Activity会销毁并重新创建。但也可以阻止系统重新创建Activity。
没有设置configChanges属性时屏幕旋转情况下的生命周期:
运行状态 → onSaveInstanceState() → onStop() → onDestroy() → onCreate() → onStart() → onRestoreInstanceState() → onResume()
设置了configChanges属性时屏幕旋转情况下的生命周期:
运行状态 → onConfigChanged()
- 手机内存不足导致低优先级的Activity被杀掉
Activity优先级划分:
1、前台Activity:正在和用户交互的Activity,优先级最高
2、可见但非前台Activity:例如弹出了一个对话框的Activity。
3、后台Activity:已经被暂停的Activity,优先级最低。
onSaveInstanceState和onRestoreInstanceState方法
这两个方法只有在Activity异常终止的情况下才会被调用,可以通过onRestoreInstanceState或onCreate方法来判断Activity是否被重建了。
onCreate和onRestoreInstanceState方法区别:
onRestoreInstanceState回调则表明其中Bundle对象非空,不用加非空判断。
onCreate需要非空判断。建议使用onRestoreInstanceState。
- 调用时机
onSaveInstanceState在onStop方法之前调用,但和onPause没有时序关系;
onRestoreInstanceState在onStart方法之后。
- 保存和恢复View层次结构
Activity被异常终止时,会委托Window保存数据,它又会委托顶层容器(DecorView)去保存数据,而它会遍历子元素依次通知它们保存数据,也就是调用相应的onSaveInstanceState和onRestoreInstanceState方法。
阻止系统配置改变时Activity发生重建
通过在AndroidMenifest.xml文件中在相应的Activity中指定**configChanges**
属性,当发生configChanges中指定的系统配置改变时就不会重建Activity,此时会回调onConfigurationChanged
方法,不会调用其他任何生命周期方法。
Activity启动模式
实例参看https://www.jianshu.com/p/b4472dc6911e
- standard:标准模式,也是Activity默认的启动模式。每次启动一个Activity都会创建它的实例并加入任务栈栈顶,不管它是否已经存在。
例如:在Activity A中有一个按钮,按下会通过startActivity再启动Activity A。如果连着点击两次,总共就会创建三个Activity实例,需要按三次返回键才能退出到桌面。 - singleTop:栈顶复用模式。如果要启动的新Activity已经在任务栈栈顶,就不会再创建新的实例,同时它的onNewIntent方法会被回调;如果它不在任务栈栈顶,就会创建新的实例。
应用
:通知栏中通过通知跳转的Activity。还有就是防止连续两次点击创建了两个Activity实例。 - singleTask:栈内复用模式。每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,如果已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,并回调onNewIntent();如果没有发现就会创建一个新的活动实例并加入任务栈顶。
应用
:大多数app的主页面Activity - singleInstance:单实例模式。新启动的Activity会单独放在一个新创建的任务栈中。
应用
:来电或闹钟页面
onNewIntent()
正常情况下如果某个Activity的启动模式为singleTask或singleTop,在第一次启动这个Activity的时候,会在栈中创建一个新的实例,也就是会调用 onCreate()→onStart()→onResume();如果栈中(singleTop对应的是栈顶)已经有了这个Activity的实例,则会调用:onNewIntent()→onResart()→onStart()→onResume()。
onNewIntent()的陷阱
在onNewIntent()中调用getIntent(),始终只会获取最开始的那个Intent对象。但我们可以在其中调用setIntent()将Intent对象更新。
也就是下面的写法在每次才会拿到最新的Intent:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent); //设置新的intent
int data = getIntent().getIntExtra("tanksu", 0);//此时的到的数据就是正确的了
}
taskAffinity
每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名
singleTask和taskAffinity配合使用,指定启动的Activity加入到哪个栈中
为Activity指定启动模式
两种方法,但设置标记位的优先级高于在xml中指定启动模式。
其次,两种方式也有区别:第一种无法直接为Activity设置FLAG_ACTIVITY_CLEAR_TOP标识;第二种无法为Activity指定singleInstance。
- 在清单文件中为Activity指定launchMode属性
- 在Intent中设置标志位。也就是给startActivity中传入的Intent对象通过**
addFlags
**方法设置。
Activity常用的Flags
- FLAG_ACTIVITY_SINGLE_TOP:和singleTop启动模式相同
- FLAG_ACTIVITY_NEW_TASK:和singleTask启动模式相同
- FLAG_ACTIVITY_CLEAR_TOP:一般需要和FLAG_ACTIVITY_NEW_TASK配合使用,此时和
**singleTask**
效果相同。如果被启动的Activity设置了standard模式,则它和其上的Activity实例都会出栈,并且重新创建这个Activity的实例加入栈顶。 - FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:有这个标记的Activity不会出现在历史Activity列表中。
启动模式和Flags的区别
启动模式和 FLAG 的区别主要在于,前者是固定的,写死在xml文件中;
后者是可组合的,比较灵活。
例如:当你多数场景下不合适使用 SingleTask,但个别场景又需要它的这种清空栈中上方 Activity 的特性,那么此时你就选用 singleTop模式 + clearTop FLAG 的组合,如此,在清单中你配置的是 singleTop,仅在你需要清空效果的场景下,在代码中动态附加 FLAG 来组合使用。