1.生命周期:
1.1 基础生命周期
老图了,就不解释详细了,重点提下:
1.1.1 Activity3种运行状态:Resumed、Paused、Stopped
Paused:这个Activity在屏幕上是可见的,但是并不是在屏幕最前端的那个Activity。比如有另一个非全屏或者透明的Activity是Resumed状态,没有完全遮盖这个Activity。
Stopped:当Activity完全不可见时,此时Activity还在后台运行,仍然在内存中保留Activity的状态,并不是完全销毁。
1.1.2 各生命周期
onStart():表示Activity正在被启动,即将开始,没有出现在前台,这时Activity已经出现了。注意:onStart时,对应Paused状态,Activity可见,不可点击(交互),不可获取焦点。
onResume():表示Activity已经可见了,并且出现在前台并开始活动。注意:onResume时,对应Resumed状态,Activity可见,可点击(交互),可获取焦点。
onPause():表示Activity暂停,仍可见,正常情况下,紧接着onStop就会被 调用。在特殊情况下,如果这个时候快速地回到当前Activity,那么onResume就会 被调用(极端情况)。onPause中不能进行耗时操作,会影响到新Activity的显 示。因为onPause必须执行完,新的Activity的onResume才会执行。 注意:onPause时,对应Paused状态,Activity可见,不可点击(交互),不可获取焦点。
onStop():表示Activity即将停止,不可见,位于后台。可以做稍微重量级的回收 工作,同样不能太耗时。注意:onStop时,对应Stopped状态,Activity不可见,不可点击(交互),不可获取焦点。
onDestory():表示Activity即将销毁,可以做一些回收工作和最终的资源回收。
1.2 特殊生命周期
onSaveInstanceState():当Activity遇到意外情况退出时调用保存数据,以下5种情况被调用:
(1)、当用户按下HOME键时。
(2)、从最近应用中选择运行其他的程序时(长按手机home键或者按下菜单键时)。
(3)、按下电源按键(关闭屏幕显示)时。
(4)、从当前Activity启动一个新的Activity时。
(5)、屏幕方向切换时(无论竖屏切横屏还是横屏切竖屏都会调用)。
注意:onSaveInstanceState和onPause没有固定时序,但两者都确定是在onStop之前调用,后文为了方便,将onSaveInstanceState放到onPause后面。
onRestoreInstanceState():只有在Activity确实是被系统回收,重新创建Activity的情况下才会被调用,用于重建时恢复数据。
注意:严格意义来说,onSaveInstanceState、onRestoreInstanceState并不算Activity的生命周期,因为它们不是一定被调用的。onRestoreInstanceState只有在Activity确实是被系统回收,重新创建Activity的情况下(即重走onCreate)才会被调用,比如旋屏,Activity确实被销毁后又重新onCreate。而HOME键切换则不会。
1.3 通常状况下生命周期调用情况
(1)针对一个特定的Activity,第一次启动,回调如下:onCreate()->onStart()>onResume()
(2)用户打开新的Activiy的时候,原Activity的回调如下:onPause()->onSaveInstanceState()->onStop()
(3)再次回到原Activity时,回调如下:onRestart()->onStart()->onResume() 注意:虽然调用了onSaveInstanceState,但onRestoreInstanceState并不会被调用。
(4)按back键回退时,回调如下:onPause()->onStop()->onDestory() 注意:因为back为主动退出行为,所以不会调用onSaveInstanceState。
(5)按Home键切换到桌面后又回到该Actitivy,回调如下:onPause()->onSaveInstanceState()->onStop()>onRestart()->onStart()->onResume() 注意:虽然调用了onSaveInstanceState,但onRestoreInstanceState并不会被调用。
(6)调用finish()方法后,回调如下:onPause()->onStop()->onDestory()
(7)横竖屏切换,回调如下:onPause() -> onSaveInstanceState() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onRestoreInstanceState() -> onResume() 注意:可以指定 android:configChanges = "orientation| screenSize" 来避免横竖屏切换时,Activity被销毁和重建,指定后,Activity不会调用onDestroy和onCreate,而是回调了下面的方法:
@Override
public void onConfigurationChanged(Configuration newConfig)
2 启动模式
2.1 标准模式 standard
每启动一次Activity,就会创建一个新的Activity实例并置于栈顶。谁启动了这个 Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中。
注意:如果在Service或Application中启动一个Activity,其并没有所谓的任务栈,可以使用标记位Flag来解决,即为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,创建一个新栈。
2.2 栈顶复用模式 singleTop
如果需要新建的Activity位于任务栈栈顶,那么此 Activity 的实例就不会重建,而是重用栈顶的实例。
注意:因为不是重建,所以不会重新调用onCreate() ,而是走onNewIntent() ,但是由于确实有启动且换界面的效果,所以生命周期为 onPause() -> onNewIntent() -> onResume() 。
同 standard模式,如果是外部程序启动singleTop的Activity,在Android 5.0之前新创建的Activity会位于调用者的Task中,5.0及以后会放入新的Task中。
2.3 栈内复用模式 singleTask
一个栈内只有一个该Activity实例,如果该Activity被重复启动,则判断栈顶的Activity是否是需要启动的Activity,不是则出栈,直到栈顶Activity是被启动的那个Activity。singleTask的Activity生命周期为:onNewIntent() -> onRestart() -> onStart() -> onResume()
注意:可以通过在 AndroidManifest文件中指定singleTask模式的Activity需要加载到那个栈中,使用taskAffinity属性。如果指定的栈不存在,则创建。
关于taskAffinity的值:每个Activity都有taskAffinity属性,这个属性指出了它希望 进入的Task。如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名。
值得一提:如果App的启动Activity被设置为singleTask,则Home键退出到桌面,然后再点击App图标进入,则会“重启”app。这里并非真正的重启,启动页Activity不会重建(不会走onCreate,走onNewIntent() -> onRestart() -> onStart() -> onResume()),应用的Application更不会重建,而是栈中启动页Activity前的其它所有Activity都被出栈了。
原因可能和Task调度相关,在Launcher启动app,会先拉起启动页Activity,然后将已有的Task调度到前台,猜测,待验证。
解决:去掉启动页的singleTask或singleInstance模式。部分机型不在这两种模式下都可能出现这个问题,如果存在,则在启动页Activity的onCreate里加上:
if (!this.isTaskRoot()) { // 判断当前activity是不是所在任务栈的根
Intent intent = getIntent();
if (intent != null) {
String action = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(action)) {
finish();
return;
}
}
Task(任务)是Android Framework中的一个概念,Task是由一系列相关的Activity组成的,是一组相关Activity的集合,以栈的形式来管理的。在启动模式为standard或singleTop时,一般是在同一个任务中对Activity进行调度,而在启动模式为singleTask或singleInstance时,一般会对Task任务进行整体调度,包括:
(1)按Home键,将之前的Task切换到后台
(2)长按Home键,会显示出最近执行过的Task列表
(3)在Launcher或HomeScreen点击app图标,开启一个新Task,或者是将已有的Task调度到前台
2.4 单例模式 singleInstance
打开该Activity时,直接创建一个新的任 务栈,并创建该Activity实例放入新栈中。一旦该模式的Activity实例已经存在于某个 栈中,任何应用再激活该Activity时都会重用该栈中的实例。系统打电话界面的Activity就是singleInstance
2.5 Activity的Flags
Activity的Flags很多,用于设定Activity的启动模式,可以在启动Activity时,通过Intent的addFlags()方法设置。 (1)FLAG_ACTIVITY_NEW_TASK 其效果与指定Activity为singleTask模式一致。
(2)FLAG_ACTIVITY_SINGLE_TOP 其效果与指定Activity为singleTop模式一致。
(3)FLAG_ACTIVITY_CLEAR_TOP 具有此标记位的Activity,当它启动时,在同一 个任务栈中所有位于它上面的Activity都要出栈。如果和singleTask模式一起出现, 若被启动的Activity已经存在栈中,则清除其之上的Activity,并调用该Activity的 onNewIntent方法。如果被启动的Activity采用standard模式,那么该Activity连同之 上的所有Activity出栈,然后创建新的Activity实例并压入栈中。
其它具体参考:https://www.jianshu.com/p/537aa221eec4/