(1)onCreate:
Activity正在被创建,这里可以做一些初始化工作,比如加载界面布局,初始化数据等。
(2)onRestart:
Activity正在被重新启动,从不可见到重新可见状态时会被调用。比如用户按Home键,或者打开了一个新的ActivityB,这时当前的ActivityA会执行onPause和onStop,当用户又回到这个ActivityA时,会调用此方法。
(3)onStart:
Activity正在被启动,此时Activity可见但是没有出现在前台,还无法和用户交互。
(4)onResume:
Activity已经可见在前台可交互。
(5)onPause:
Activity正在停止,这里可以做一些存储数据,停止动画等工作,但是不能太耗时,避免影响新的Activity显示。因为必须要onPause先执行完,新的Activity的onResume才会执行。
(6)onStop:
Activity即将停止,这里也可以做一些稍微重量级的回收工作,同样不能太耗时
(7)onDestroy:
Activity即将被销毁,生命周期最后一个回调,可以做回收工作和最终的资源释放。
Q1、Activity第一次启动,回调过程?
Q2、用户打开新的Activity或者home键回到桌面,回调过程?
Q3、用户打开新的透明主题Activity,回调过程?
Q4、用户再次回到原Activity,回调过程?
Q5、用户back键回退,回调过程?
Q6、当前ActivityA打开新的ActivityB,B的onResume和A的onPause哪个先执行?
公布答案:
在实际开发中,除了用户操作导致的正常生命周期调度,还会有一些异常的情况,比如系统内存不足Activity可能被杀死,或者切换横竖屏导致Activity被杀死。
所以我们还要掌握异常情况下的生命周期调用,有助于我们写出更优秀的代码。
情况一、资源相关配置发生改变导致Activity被杀死并重新创建,以旋转屏幕为例
被杀死也就是Activity被销毁,onPause,onStop,onDestroy都会被调用的,除此之外,系统还会调用onSaveInstanceState,来保存当前Activity的状态,调用时机可能在onPause之前也可能在onStop之前。系统会为我们默认保存什么呢?比如当前Activity的视图结构,文本框中用户输入的数据,listview滚动滚动位置等。
当Activity重建的时候,系统会执行onRestoreInstanceState,把销毁时存在onSaveInstanceState里面的Bundle对象作为参数传递给onRestoreInstanceState和onCreate方法,所以我们取数据时候两个方法都可以取,区别是onRestoreInstanceState中取不需要判空,而onCreate中需要判断budle是否为空。
需要强调的点:系统只在Activity异常终止的时候会调用onSaveInstanceState和onRestoreInstanceState,正常情况不会触发这个过程。
情况二、资源内存不足导致低优先级Activity被杀死
数据存储和回复过程和情况一是一样,Activity的优先级从高到低可以分为如下三种:
当系统内存不足的时候,会按照优先级的顺序,先杀死优先级低的Activity。
Android提供了四种启动模式,standard、singleTop、singleTask、singleInstance.
Android系统默认情况下(默认standard模式),每次打开同一个Activity都会创建一个实例放到任务栈中,当我们按back键的时候,栈中实例会一个一个回退,直到栈空为止,当栈中没有任何Activity实例之后,系统会回收这个任务栈。这种多次重复创建同一个Activity实例的模式,很多场景不适用,所以Android系统提供了其他几种。
1. standard:标准模式
系统默认就是标准模式,每次启动Activity,都会创建一个实例放到任务栈中,不管栈中是否已经有了该Activity的实例。也就是说,在该模式下,一个任务栈中可以有多个实例,每个实例也可以属于不同的任务栈。例如在该模式下,ActivityA打开了ActivityB(standard模式下),那么ActivityB 就会默认进入到A的栈中。
注意:Activity的Context有任务栈,非Activity类型的Context,比如ApplicationContext就没有任务栈,所以用ApplicationContext打开一个Activity会报错。解决办法是启动Activity的时候指定FLAG_ACTIVITY_NEW_TASK标记位,这样就会为这个Activity创建一个任务栈。
2.singleTop栈顶复用模式
D已经在栈顶,singleTop模式下打开D,栈内情况如上图。另外因为D Activity不会被重建,所以它的onCreate、onStart不会被调用,onNewIntent方法会被回调。
如果是以standard模式打开D,栈内情况如下:
3.singleTask栈内复用模式
三个例子了解singleTask模式
启动方式有两种。
第一种:清单文件中指定
第二种:通过在Intent中设置标记位来指定
Intent intent = new Intent(this,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
区别:
1、优先级方面,如果同时存在,以第二种方式为准,因为第二种方式优先级高于第一种
2、限定范围方面,第一种无法设定FLAG_ACTIVITY_CLEAR_TOP,第二种方式无法指定singleInstance模式。
大部分情况下,我们不需要为Activity指定标记位,所以对于标记位理解即可。列举几个比较常用的:
FLAG_ACTIVITY_NEW_TASK,为Activity指定singleTask模式
FLAG_ACTIVITY_SINGLE_TOP,为Activity指定singleTop模式
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有该标记的Activity不会出现在历史Activity列表中。当我们不希望用户通过历史列表回到这个Activity的时候使用。
Activity的启动方式大致分两种,显式启动和隐式启动。
显示启动常见写法:
Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);
隐式启动:需要在清单文件中,在所需要打开的Activity中添加过滤器,也就是IntentFilter,举了例子:
这里梳理一下IntentFilter的匹配规则。
://:/?
eg: http://www.baidu.com:80/search/info
注意intent设置的时候要用setDataAndType(),因为setData和setType会彼此清除对方的值。
过滤规则如果没有设置URI,是有默认值的,URI默认值是content和file。
以上知识点均整理来自任玉刚的《Android开发艺术探索》
推荐两篇启动模式相关的面试题文章:
程序员何苦为难程序员(上)
程序员何苦为难程序员(下)