Activity的生命周期和启动模式
1.1 Activity的生命周期分析
Activity的生命周期分为两个部分,一个是典型情况下的生命周期,另一个是异常情况下的生命周期。所谓的典型情况下的生命周期是指,是指有用户参与的情况下,Activity所经过的生命周期的改变。而异常情况下的生命周期是指Activity被系统回收,或者当前设备的Configuration发生改变从而导致Activity被销毁重建。
1.1.1 典型情况下的生命周期
在正常情况下,Activity会经历的生命周期有:
- onCreate:表示Activity正在被创建,我们可以在这个方法中做一些初始化的工作。
- onStart:表示Activity正在被启动,这个时候Activity已经可见了,但是还没有出现在前台,还无法和用户交互。(可以理解为Activity已经显示出来了,但是我们还看不见)
- onRestart:表示Activity重新启动,此时Activity从不可见状态变为可见状态时,onRestart就会被调用。
- onResume:表示Activity已经可见了,并且出现在前台。当Activity界面获取焦点的时候(界面按钮可以被点击,文本框可以输入内容)。
- onPause:表示Activity已经停止,此时Activity界面失去焦点的时候(界面按钮不可以被点击,文本框不可以输入内容,但是界面,用户仍然能看见)。此方法通常用于确认对持久性数据的未保存更改、停止动画以及其他可能消耗 CPU 的内容,不能做很耗时的操作。
- onStop:表示Activity即将停止,此时Activity界面用户不可见时。可以做稍微重量级的回收工作,但是也不能太耗时。
- onDestroy:表示Activity即将被销毁,可以做一些回收工作和最终的资源释放。
可将Android典型情况下的生命周期分为三种
- 完整的生命周期
onCreate-->onStart-->onResume-->onPause-->onStop-->onDestroy - 可视生命周期
onStart-->onResume-->onPause-->onStop - 前台生命周期
onResume-->onPause
下面是google官方给出的Activity生命周期的切换过程:
需要注意的问题
因为前一个Activity执行完成onPause方法以后新Activity的onResume才能执行。所以我们如果在onPause或者onStop中执行耗时操作,尽量在onStop中执行。
1.1.2 异常情况下的生命周期分析
当系统配置发生变化时,或者系统内存不足时,Activity可能被杀死。
- 资源相关的系统配置发生改变导致Activity被杀死并重新创建。
当系统配置发生改变后,Activity会被销毁onPause、onStop、onDestroy都会被调用。 - 除此以外系统还会调用onSaveInstanceState来保存当前的Activity的状态。这个方法的调用时机是在onStop之前,和onPause没有什么时序关系。该方法正常情况下不会被调用,只有Activity以外终止的时候才会被调用。
- Activity重新被创建的时候,系统会调用onRestoreInstanceState,我们可以通过该方法取出,onSaveInstanceState方法中所保存的数据。该方法的调用时机发生在onStart之后。
- 资源内存不足导致低优先级的Activity被杀死
Activity按照优先级从高到低的可以分为三种: - 前台Activity——————正在和用户交互的Activity,优先级最高。
- 可见但非前台Activity——————比如Activity弹出个对话框。
- 后台Activity——————已经被暂停的Activity,比如执行了onStop,优先级最低
Tips:
当系统配置改变后,Activity会被重新创建,如果想Activity不被系统重新创建那么我们可以设置Activity的configChanges属性。
android:configChanges="orientation|screenSize"
Activity的启动模式
activity的启动模式共有四种。
- standard:标准模式,也是系统的默认模式。每次启动一个Activity都会重新创建一个新的实例。这种模式下,谁启动了这个Activity,那么这个Activity就在启动它那个Activity的堆栈中。
Tips:
ApplicationContext启动standard模式的Activity的时候会报错。因为非Activity的Context并没有任务栈。要解决这个问题的方法,为带启动Activity指定FLAG_ACTIVITY_NEW_TASK标记为。
- singleTop:栈顶复用模式。如果新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时他的onNewIntent方法会被回调。如果不是位于栈顶,那么新的Activity仍然会被重新创建。
-
singleTask:栈内复用模式。这是一种单实例模式,这种模式下只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,系统也会回调onNewIntent。
注意: - 任务栈S2和ActivityD两个都不存在,那么系统先创建任务栈S2,然后将D的实例压入到栈S2中。
- 如果存在S2直接将D的实例压入到栈S2中。
- singleTask启动模式自带cleartop的功能,例如ABCD,四个Activity,从栈顶到栈底。如果这时候启动DActivity那么任务栈中只剩下D的实例。
- singleInstance:单实例模式,加强的singleTask模式,除了具有singleTask的所有特性以外,这种模式的Activity只能单独位于一个任务栈中。
Activity的Flags
主要介绍一下比较常用的Flags
- FLAG_ACTIVITY_NEW_TASK:这个标记位的作用是为Activity指定“singleTask”启动模式。
- FLAG_ACTIVITY_SINGLE_TOP:这个标志位的作用是为Activity指定"singleTop"启动模式。
- FLAG_ACTIVITY_CLEAR_TOP:当这个activity启动的时候,在同一个任务栈中位于它上面的Activity都要出栈。
-
FLAG_ACTIVITY_EXCLUDE_RECENTS:具有这个标记的Activity不会出现在历史的Activity的列表中,当某些情况下我们不希望用户通过历史列表返回到我们的Activity可以使用这个。等同于在XML中指定Activity的属性
android:excludeFromRecents="true"
IntentFilter的匹配规则
我们知道启动Activity分为两种,显示调用和隐式调用。显示调用需要指定被启动对象的组件信息,包括包名类名,而隐式调用需要明确指定组件信息。隐式调用需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息。下面我们来介绍一下IntentFilter中的各种属性和匹配规则。
- action的匹配规则:action是一个字符串,action的匹配要求Intent中的action存在并且必须和过滤规则中的其中一个action相同,action区分大小写。
- category的匹配规则:category是一个字符串,Intent中的每一个category都必须和过滤规则中的category相同。Intent中可以没有category,仍然可以匹配成功。因为系统在调用startActivity或者startActivityForResult的时候会为Intent加上“android.intentcategory.DEFAULT”这个category。
-
data的匹配规则:data的语法
<pre><code>
< data android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:pathPattern="string"
android:pathPrefix="string"
android:mimeType="string"/>
</pre></code>
data由两部分组成,mimeType和URI。mimeType指媒体类型,比如image/jpeg、audio/mpeg4generic和video/*等,可以表示图片、文本、视频等不同的媒体格式,而URI中包含的数据就比较多了。下面是URI的结构:
<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
content://com.example.project:200/folder/subfolder/etc
http://www.baidu.com:80/search/info
下面介绍每个数据的含义。
- Scheme:URI的模式,比如http、file、content等。如果URI中没有指定scheme,那么整个URI的其他参数是无效的。
- Host:URI的主机名,比如www.baidu.com,如果host未指定,那么整个URI的其他参数是无效的。
- Port:URI中的端口号,比如80,当URI中的scheme和host参数指定的时候,port参数才有意义。
- Path、pathPattern和pathPrefix:这三个参数表示路径信息。
- path:表示完整路径信息
- pathPattern:表示完整路径信息,但是它里面可以包含通配符“ * ”,“ * ”表示0个或者多个字符。
- pathPrefix:表示路径前缀信息。
注意:
如果要为Intent指定完整的data,必须调用setDataAndType方法,不能先调用setData在调用setType,因为两个方法彼此会清除对方的值。