前言:
Activity作为四大组件之一,中文翻译直接翻译为“活动”,是日常应用中与用户交互的接口,它提供了供用户操作的窗口,正常情况下,除了Window、Dialog和Toast,我们能见到的界面只有Activity。
学习清单:
Activity的生命周期Activity的启动模式IntentFilter的匹配规则
一、Activity的生命周期
1.1 典型情况下的生命周期分析
1.1.2 Activity常用的生命周期
onCreate:表示Activity正在被创建,生命周期的第一个方法。onRestart:表示Activity正在重新启动。onStart:表示Activity正在被启动。onResume:表示Activity是可见的,出现在前台并且开始活动。onPause:表示Activity正在停止。onStop:表示Activity即将停止。onDestory:表示Activity即将被销毁。
图 1-1
问:一个Activity的生命周期中可能会出现哪几种情况?
(1)Activity第一次启动时,回调有:onCreate -> onStart -> onResume。
(2)用户打开新的Activity或者切换到桌面时:onPause -> onStop。若Activity采用了透明主题,则Activity不会回调onStop。
(3)用户再回到原Activity时:onRestart -> onStart -> onResume。
(4)用户按Back键回退时:onPause -> onStop -> onDestroy。
(5)当Activity被系统回收再打开时,生命周期与(1)一样。
(9)onCreate和onDestroy分别标识着Activity的创建和销毁,在整个生命周期中只有一次调用。
问:onStart、onStop和onResume、onPause有什么区别?
onStart和onStop分别标识着Activity的开始和停止,前者Activity可见,后者Activity不可见。onResume和onPause分别标识着Activity的继续和暂停。前者Activity在前台,后者Activity在后台。
1.2 异常情况下的生命周期分析
1.2.1 资源相关的系统配置发生改变导致Activity被杀死并重新创建
图1-2
举个例子:当前Activity处于竖屏状态,如果突然旋转屏幕,由于系统配置发生了改变,在默认情况下,Activity就会被销毁并重新创建,其生命周期如图1-2所示。
分析:当系统配置发生更改后,
Activity会被销毁,其onPause、onStop、onDestroy都会被调用,由于Activity是在异常情况下终止的,系统会调用onSaveInstanceState来保存当前Activity的状态(这个方法只会出现在Activity异常终止的情况下,正常情况下不会调用这个方法)。
当Activity被重新创建后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象作为参数传递给onRestoreInstanceState和onCreate方法。
因此,可以通过onRestoreInstanceState和onCreate方法来判断Activity是否被重建了,如果被重建了,我们就可以取出之前保存的数据并恢复,从时序上来说,onRestoreInstanceState的调用时机在onStart之后。
1.1.2资源内存不足导致优先级低的Activity被杀死
Activity优先级从高到低可以分为以下三种:
前台
Activity——正在和用户交互的Activity,优先级最高。可见但并非前台
Activity——比如Activity中弹出一个对话框,导致Activity可见,但是位于后台无法和用户交互。后台
Activity——已经被暂停的Activity,比如执行了onStop,优先级最低。
当系统内存不足时,系统就会按照上述优先级去杀死目标Activity所在的进程,并在后续onSaveInstanceState和onRestoreInstanceState来存储和恢复数据。
1.2 Activity的启动模式
1.2.1 Activity 的LaunchMode
任务栈:一种“先进后出”的栈结构,存放
Activity实例。
问:Activity有哪几种启动模式?
(1)standard:标准模式,也是系统的默认模式,每次启动Activity都会重新创建一个新的实例,不管这个实例是否已经存在。
(2)singleTop:栈顶复用模式,如果新的Activity位于任务栈的栈顶,那么此Activity不会被重新创建,同时它的onNewIntent方法会回调。
(3)singleTask:栈内复用模式。一种单实例模式,在这种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,和singleTop一样,系统也会回调onNewIntent。
- 比如任务栈S1中有ABC,这个时候Activity D以
singleTask模式请求启动,其所需的任务栈为S2,由于S2和D的实例都不存在,系统会先创建任务栈S2,然后再创建D的实例并将其入栈到S2。- 假设D所需的任务栈为S1,其他情况与上述一样,由于S1存在,所以系统会直接创建D 的实例并将其入栈到S1。
- 如果D所需的任务栈为S1,并且当前任务栈S1的情况为ADBC,此时D不会被创建,系统会把D切换到栈顶并调用其
onNewIntent方法,singleTask默认具有clearTop效果,导致栈内所有在D上面的Activity全部出栈,最终S1中的情况为AD。
(4)singleInstance:单实例模式,一种加强的singleTask模式,除了singTask模式的所有特性外,还加强了一点,那就是具有此种模式的Activity只能单独地位于一个任务栈中。
举个启动模式的小例子:
假设目前有两个任务栈,前台任务栈情况为AB,而后台任务栈情况为CD,假设CD的启动模式均为singleTask。现在请求启动D,那么整个后台任务都会切换到前台,这个时候按下back键的后退列表为ABCD,如图1-3。如果请求启动D而不是启动C,后退列表为ABC,如图1-4。
图1-3
图1-4
问:在singleTask启动模式中,多次提到某个Activity所需的任务栈,什么是Activity所需的任务栈?
参数
TaskAffinity标识了一个Activity所需要的的任务栈的名字,默认情况下,此参数为应用的包名,可以自己指定,TaskAffinity属性主要和singleTask启动模式或者allowTaskReparenting属性配对使用,在其他情况下没有意义。
任务栈分为前台任务栈和后台任务栈,后台任务栈中的Activity处于暂停状态。
当
TaskAffinity和singleTask启动模式配对使用时,它是具有该模式的Activity的目前任务栈的名字,带启动的Activity会运行在名字和TaskAffinity相同的任务栈中。
当
TaskAffinity和allowTaskReparenting结合的时候,当一个应用A启动应用B 的某个Activity后,这个Activity的allowTaskReparenting属性为true的话,那么当应用B被启动后,此Activity会直接从应用A的任务栈转移到应用B的任务栈中。
1.2.2 Activity的Flags
Activity常用的标记位:
FLAG_ACTIVITY_NEW_TASK:为Activity指定“singleTask”启动模式。
FLAG_ACTIVITY_SINGLE_TOP:为Activity指定“singleTop”启动模式。
FLAG_ACTIVITY_CLEAR_TOP:具有此标记位的Activity,当它启动时,在同一任务栈所有位于它上面的Activity都要出栈,此标记一般会与singleTask一起出现。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有此标记的Activity不会出现在历史Activity的列表中,等同android:excludeFromRecents = "true"。
1.3 IntentFilter的匹配规则
启动Activity分为两种,显示调用和隐式调用。显示调用需要明确指定被启动对象的组件信息,包括包名和类名,而隐式调用则不需要明确指定组件信息。
隐式调用:
Intent能够匹配目标组件中的action、category、data这三个过滤信息,只有一个Intent能同时匹配这三种过滤信息才算完全匹配。
-
只有一个
intent同时匹配action、category、data才算完全匹配,只有 完全匹配 才能启动activity。 -
一个
activity可以 有多个intent-filter,一个intent只要成功匹配任意一组intent-filter就可以启动activity。
A. action的匹配规则
-
action的匹配要求Intent中的action存在且必须和过滤规则中的其中action相同。 -
action是区分大小写的。
B. category的匹配规则
-
ntent中的category只要有一个和 匹配规则中的category相同就可以匹配。 -
intent不设置category,也可以和其匹配,因为系统在调用startActivity或者startActivity ForResult的时候会自动添加android.intent.category.DEFAULT这个category。
C. data的匹配规则
-
类似于
action。 -
如果过滤规则中有
data,那么intent中也必须定义可匹配的data。 -
data由 两部分组成:mimeType和Url。说明:
Url默认值为content和file。如果Intent指定完整的data,必须调用setDataAndType方法。
1.4 问题扩展
1.onStart和onResume、onPause和onStop 从描述上差不多,对我们来说有什么实质上的不同?
onStart和onResume是从Activity是否可见的角度来回调的,onPause和onStop是从Activity是否在前台来回调的。
2.假设当前Activity为A,如果这时用户打开一个新ActivityB,那么B的onResume和A 的onPause哪个先执行?
A的
onPause先执行。
3.当系统配置发生变化时,Activity会被重新创建,有什么办法能够不重新创建?
可以给Activity指定
configChanges属性。例如不想让Activity旋转时重新创建,可以给configChanges属性添加orientation这个值。android:configChanges="orientation"
本文参考:
- 《Android开发艺术探索》
- IntentFilter的匹配规则