Activity的要点
1、生命周期
2、启动模式(显示与隐式)
3、加载模式
4、启动过程
生命周期
Activity的生命周期主要包括两种:
第一种运行环境良好
用户正常操作APP页面,屏幕方向不变、内存充足等;
第二种是异常情况下
Activity的生命周期受到了运行环境改变影响,从而被系统杀死。
在第一种情况中,Activity的生命周期大致如下图一:
当出现页面部分被遮挡从而使用户无法与此Activity进行交互时(如:页面中弹出了对话框遮挡住了Activity),Activity的onPause方法就会被调用。如果Activity重新回到前台状态(可交互状态),那么onResume方法会重新被调用。此过程是图一中蓝色箭头所显示的流程
如果Activity A正处于可交互状态,此时页面跳转到另一个页面Activity B,生命周期函数会依次被调用:Activity A 的onPause----Activity B 的onCreate-------Activity B的onStart------Activity B 的onResume-------Activity A 的onStop。当页面再次回到Activity A的时候,会调用Activity B的onPause-----------Activity A的onRestart-------Activity A的 onStart--------Activity A 的onResume------Activity B的onStop。此过程是图一紫色箭头所显示的流程。
在第二种情况中,也分两种异常情况。
第一种异常情况是指与资源相关的系统配置发生变化,如将手机语言进行更改,或者是手机的屏幕方向发生了改变,都会使Activity被重新创建加载,除非Activity中configChanges属性配置了对应的值。在异常情况下,Activity发生被回收重新创建,其onPause、onStop、onDestory方法均被调用。同时在调用onStop方法之前还调用了另一个方法onSaveInstanceState方法将页面的状态进行保存(至于如何对Activity状态进行保存就需要去阅读相关源码才知道,不过书中提到系统是运用了委托机制来进行状态的保存)。在该Activity再次被创建时,系统会调用onRestoreInstanceState方法,并将onSaveInstanceState方法中保存的Bundle对象来作为参数传递给onRestoreInstanceState方法,此过程如图二所示。
第二种异常情况,当手机运行内存不足会导致优先级别较低的Activity所在的进行被杀死。Activity按照优先级别从高到低可以分为:前台交互的Activity优先级别最高、其次是可见但无法交互的Activity、最低级别是处于系统后台被暂停的Activity。在手机内存不足的情况下,系统会优先杀死优先级别低的Activity所在进程。同样的,在此过程中Activity的生命周期跟第一种异常情况是一样的,此过程如图一红色箭头所示。
小结:
主要看熟上面两张流程图即可
启动模式
启动Activity的方式包括了显式和隐式,显示启动相对简单,这里主要是讲解如何通过IntentFilter的匹配来隐式启动Activity。在清单文件中,Activity标签中可以包含多个IntentFilter匹配规则。每个匹配规则中都是由action、category、data三个标签来定义规则。只有完全匹配到某一个IntentFilter,才会启动对应的Activity。如何才算完全匹配到呢?在IntentFilter中的所定义的属性都分别满足相应的action、category、data的匹配规则。
1)action的匹配规则:
action的字符串值必须完全一样,区分字母的大小写。如果一个IntentFilter中定义了多个action,intent必须满足其中一个。
2)category的匹配规则:
所有隐式启动Activity都会自动在intent中加入了category值为:android.intent.category.DEFAULT
。所以在IntentFilter中必须定义
<category android:name="android.intent.category.DEFAULT"/>
由于所有的隐式启动都会自动加入category,所以可以设置intent的category,也可以不设置。但是如果intent中设置了category,那么就必须跟IntentFilter中的有匹配。
3)data的匹配规则:
data匹配分两部分,mimeType和URI。
mimeType指媒体类型,
而URI包含的字段有:scheme、host、port、path、pathPattern、pathPrefix
data中如果没有设置scheme的值,默认是content或者file。
如果IntentFilter中设置了data,那么intent中就必须设置data并且跟其中某一个data。这里匹配成功是指过滤条件中的部分data出现在Intent中的data。
加载模式
书中分别介绍了Activity的四种加载模式:standard、singleTop、singleTask、singleInstance。
第一种加载方式相对容易理解,在标准模式下启动,被启动的Activity将会加载到启动它的Activity所在的任务栈中,所以如果被加载的Activity不是由Activity的context来启动加载的,那么就会报错,书中举了ApplicationContext通过标准模式下加载Activity就会报异常这个例子。此模式下Activity如果多次被加载,会出现多个实例。
第二种加载模式singleTop是指栈顶复用。意思就是如果Activity的实例是位于栈顶,再次以栈内复用的方式加载的话,该Activity不会被重新创建出新的实例,而是重复利用已经位于栈顶的实例,所以被重用的实例都会在被重新调用的时候加载它的onNewIntent方法。如果将要被启动的Activity的实例不是位于栈顶,那么还是会被重新创建新的实例。
第三种Activity加载方式singleTask是指栈内复用。栈内复用是指Activity实例所需要的任务栈中已经存在一个将要被加载的Activity的实例,那么该实例将会被复用。同时,如果实例被重用,所有位于该实例顶的实例都会被清出该任务栈,符合clearTop原则。跟singleTask配合使用的还有一个Activity的属性,TaskAffinity。该属性可以指定加载的Activity到哪个任务栈。默认情况下所有的Activity都是加载都以包名相同的任务栈中。
第四种加载模式singleInstance。这是一种比较少用到的模式,在全局中单例模式。意思就是在整个应用中,如果某个Activity以这种方式加载启动,那么系统会新创建一个任务栈,并且创建一个Activity的实例入栈。
设置Activity加载模式的方法有两种,一种是通过清单文件来设置,另外一种是通过Java代码中启动跳转的时候设置标示位来实现,两种方式的区别不是很大,但第一种方式无法设置FLAG_ACTIVITY_CLEAR_TOP标识,第二种方法无法为Activity设置singleInstance模式,并且如果两种方式都设置了,那么以第二种方式为主。
启动过程
将Activity组件划分为两种类型:一种是根Activity,一种是子Activity。根Activity以快捷图标的形式显示在应用程序启动器中,它的启动代表了一个Android应用程序的启动过程。
根Activity组件的启动过程
Launcher组件启动MainActivity组件的过程如下:
(1)Launcher组件向ActivityManagerService发送一个启动MainActivity组件的进程间通信请求。
(2)ActivityManagerService首先将要启动的MainActivity组件的信息保存下来,然后再向Launcher组件发送一个进入中止状态的进程间通信请求。
(3)Launcher组件进入到中止状态之后,就会向ActivityManagerService发送一个进入中止状态的进程间通信请求,以便ActivityManagerService可以继续执行启动MainActivity组件的操作。
(4)ActivityManagerService发现用来运行MainActivity组件的应用进程不存在,因此先启动一个新的应用程序进程。
(5)新的进程启动完成后就会向ActivityManagerService发送一个启动完成的进程间通信请求
(6)ActivityManagerService将第二步保存下来的MainActivity组件信息发送给第四步创建的应用程序进程,以便它可以将MainActivity组件启动起来。
子Activity组件在新进程中启动过程
(1)MainActivity组件向ActivityManagerService发送一个启动SubActivityInNewProcess组件的进程间通信请求。
(2)ActivityManagerService首先将需要启动的SubActivityInNewProcess组件信息保存下来,然后向MainActivity发送进入中止状态的进程间通信请求。
(3)MainActivity进入中止状态后就向ActivityManagerService发送一个已进入中止状态的进程间通信请求。
(4)ActivityManagerService发现用来运行SubActivityInNewProcess组件的应用程序进程不存在,先会启动一个新的应用程序进程。
(5)新的应用程序进程启动完成后就会向ActivityManagerService发送一个启动完成的进程间通信。
(6)ActivityManagerService将第二步保存下来的SubActivityInNewProcess组件信息发送给第四步创建的进程,以便它可以将SubActivityInNewProcess组件启动起来。