想要彻底弄清楚Activity在不同情况下的生命周期需要先掌握Activity的一些基础知识
知道了Activity完整的生命周期之后还需要知道Activity的启动模式。
Activity四种启动模式:
standard:
默认的启动模式,每次通过这种模式启动目标Acitivity,都创建一个新的实例,并将该Activity添加到当前栈顶。
singleTop:
只有当Activity位于栈顶时,系统才不会重新创建目标Activity的实例,而是直接复用已有的Activity实例。否则创建一个新的实例。这种模式经常被用在新闻展示页,当推送过来一条新闻,跳转到新闻页显示,如果你正在看新闻,就不需要重复的创建这个activity
singleTask:
如果栈中不存在目标Activity时,则创建目标Activity实例。
如果栈中存在目标Activity时,
(1)已经位于栈顶,此时与singleTop行为相同
(2)不位于栈顶,系统会使该Activity上面所有的Activity出栈。
singleInstance:
如果栈中不存在目标Activity,系统会创建一个新的任务栈,再创建Activity实例,将它加入该栈中
如果栈中存在该Activity,无论哪个应用程序调用,都不会创建新的Activity
---------------------
举例
假设有两个Activity A、B
standard模式
当A启动到从A跳转到B的生命周期
A启动时:onCreate -> onStart -> onResume
从A跳转到B时:A.onPause -> B.onCreate -> onStart -> onResume -> A.onStop
按back键返回时:B.onPause -> A.onReStart -> onStart -> onResume -> B.onStop -> onDestroy
singleTop模式
设定A为singleTop,启动A,从A跳A,就是在栈顶时会不会创建A的实例
A启动时:onCreate -> onStart -> onResume
从A跳A时:onPause -> onResume
按back键返回时:onPause -> onStop -> onDestroy
可以看到并没有重新创建A的实例,只是执行了onPause 和onResume
singleTask模式
设定A为singleTask,启动A,从A跳B,再从B跳A
A启动时:onCreate -> onStart -> onResume
从A跳转到B时:A.onPause -> B.onCreate -> onStart -> onResume -> A.onStop
从B跳转到A时:B.onPause -> A.onReStart -> onStart -> onResume -> B.onStop -> onDestroy
可以看到当A在栈中存在时,再次跳转不会创建A的实例并使A上面的B出栈
singleInstance模式
为 singleInstance 模式时,activity独占一个task,现在有以下三个activity: Act1、Act2、Act3,其中Acti2 为 singleInstance 模式。它们之间的跳转关系为: Act1 – Act2 – Act3 ,现在在Act3中按下返回键,由于Act2位于一个独立的task中,它不属于Act3的上下文activity,所以此时将直接返回到Act1,Act1再按下返回键时到Act2,这就是singleInstance模式。
看完四种模式,这里会有疑问:
为什么要先执行A的onPause方法,再执行B的生命周期方法?
为什么不是执行完A的onStop方法之后再执行B的生命周期方法?
首先来看第一个问题,假如A正在播放一段音乐,如果先执行B的生命周期,再执行A的onPause方法,就会出现B已经显示出来,A中的音乐还在播放的异常情况。而如果先执行了A的onPause方法,我们就可以在其中执行一些操作来暂停音乐的播放。原本onPause方法的设计职责即使如此。
对于第二个问题,由于Activity的可见生命周期是onStart()到onStop(),假如先执行A的onPause()和onStop(),再执行B的生命周期,每次切换的时候就会出现黑屏的情况,这种切换效果显然是不优雅的。
注:
建议在onCreate()中调用setContentView()、findViewById()
建议在onResume()中打开独占设备(比如相机)、开启动画等
建议在onPause()中执行关闭独占设备、停止动画等比较耗CPU的操作,但不要执行比较耗时的操作,底层执行Activity的onPause()时,有一定的时间限制的,当ActivityManagerService通知应用进程暂停指定的Activity时,如果对应的onPause()在500ms内还没有执行完,ActivityManagerService就会强制关闭这个Activity。
onStop()中可以执行一些比较耗时的操作,这是在后台执行所以也不影响用户的体验
附:
伴随着activity常用的除了生命周期还有两个方法,onSaveInstanceState 和 onNewIntent
1.onSaveInstanceState
我们都知道不同的手机,内存不同,系统在内存不足的时候很有可能就会把你APP中不再栈顶的activity给回收掉。如果这个activity无关紧要那就啥也不说了,但是就怕它对你来说很重要。这个时候你不对它进行保护措施的话,你就等着哭吧。比如你打开了A,A是一个注册类activity。然后你填写了一堆信息后,返回桌面去看了一条短信,或者接了一个电话,等你再打开这个的时候你发现里面填写的东西都不见了,这个时候你想不想一巴掌拍死这个开发人员?
所以呢onsaveinstancestate()就可以闪亮登场了,虽然你也可以使用其他保存机制去处理,但是对于这种情况,onsaveinstancestate()依然是最佳的选择。onsaveinstancestate()方法有的同学有可能没见过 但是savedinstancestate相必都见过,就是在oncreate()方法的那个括号里面,savedinstancestate是一个bundle类型的参数,bundle有很多保存数据的方法这个你想必是知道的吧,对我们就是利用这个去保存数据。onsaveinstancestate()回调方法会保证一定在activity被回收之前调用
onSaveInstanceState方法会在什么时候被执行,有这么几种情况:
当用户按下HOME键时。
长按HOME键,选择运行其他的程序时。
按下电源按键(关闭屏幕显示)时。
从activity A中启动一个新的activity时。
屏幕方向切换时,例如从竖屏切换到横屏时。
当按下HOME键或者锁屏时,会执行onPause -> onSaveInstanceState -> onStop
当从activity A跳转到 B 时,A.onPause -> B.onCreate -> onStart -> onResume -> A.onSaveInstanceState -> A.onStop
使用:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_one);
if (savedInstanceState != null) {
String oldString = savedInstanceState.getString("Activity");
Log.e(TAG,"oldString="+oldString);
}
Log.e(TAG,"onCreate");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.e(TAG,"onSaveInstanceState");
String string = "activity 被系统回收了怎么办?";
outState.putString("Activity", string);
}
2.onNewIntent
如果activity设置为singleTask或者signleTop模式【当调用startActivity方法时,这两种模式不会重新创建activity,只会调用onNewIntent方法,当然任务栈中没有销毁该activity的情况下】,再向activity传值时,就可以利用onNewIntent
执行顺序:onNewIntent -> onReStart -> onStart -> onResume
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.e(TAG,"onNewIntent");
setIntent(intent);
String msg = getIntent().getExtras().getString("msg");
Log.e(TAG,"msg="+msg);
}
//另一个activity中发送
Intent intent = new Intent(this,OneActivity.class);
intent.putExtra("msg","传值过来");
startActivity(intent);
---------------------