七个生命周期
onCreate onRestart onStart onResume onPause onResume onDestory
(1)当第一次开始新的活动时,调用如下:onCreare -> onStart -> onResume
(2)当用户打开新的Activity或者回到桌面时,从前台到后台,从可见到不可见,因此调用onPause -> onStop
,当新活动时透明主题的时候只调用onPause
(3)当用户再次回到活动时,从不可见到可见,从后台到前台,因此调用如下:onRestart -> onStart -> onResume
(4)当用户按back键回退的时候,从前台到后台,从可见到不可见,从返回栈中移除活动,因此回调如下:onPause -> onStop -> onDestory
(5)当活动被系统回收后再次打开,生命周期和(1)一样,但不是完全一样。
当前的活动为A,打开一个新的活动B,是A先onPause还是B先onResume?
(1)首先看Activity的启动过程。
首先启动请求会由Instrumentation来处理,它通过binder来启动ActivityManagerService。ActivityManagerService内部维护了一个ActivityStack,AMS通过ActivityThread去同步Activity的状态从而完成生命周期方法的调用。ActivityStack需要先onPause才能启动新的Activity。然后在realStartActivityLocked方法会调用ApplicationThread的scheduleLaunch方法,scheduleLaunch会完成onCreate,onStart,onResume的调用过程。scheduleLaunch最终调用handleLaunchActivity,完成onCreate,onStart,onResume的调用。因此为了保证Acitivity之间尽快切换,不要在onPause方法中做重量级的操作。
异常情况下的生命周期
当资源相关的系统配置发生改变的时候,系统会销毁当前的Activity并重新创建,比如当手机从竖屏变成横屏的时候。
销毁之后,onPause, onStop和onDestory方法都会被调用。由于是异常终止,系统会调用onSaveInstanceState来保存当前活动的状态,当活动被重新创建的时候,会调用onRestoreInstanceState,将onSaveInstanceState是保存的Bundle同时传递给onRestoreInstanceState和onCreate方法。onRestoreInstanceState的调用在onCreate方法之后。
异常情况下保存和恢复View层次结构
首先Activity会调用onSaveInstanceState保存数据,然后委托Window保存数据,Window委托给上层容器,顶层容器是ViewGroup,一般情况下是DecorView。最后顶层容器一一通知子元素来保存数据。比如TextView的onSaveInstanceState就保存了当前的文本选中状态和文本内容。官方建议使用onRestoreInstanceState来恢复数据,因为Bundle savedInstanceState是一定有值的。
内存不足杀死优先级低的Activity
优先级从高到低:前台Activity,可见非前台Activity,后台的Activity。系统会按上述的优先级杀死进程,并通过onSaveInstanceState和onRestoreInstanceState来存储和恢复数据。可以在Activity的configChanges属性中指定选项,当该选项发生改变的时候Activity不会重新创建。
Activity的启动模式
(1)standard标准模式:每次启动一个新的Activity就会创建一个新的实例。如果用ApplicationContext去启动standard模式的Activity会报错,因为Activity会进入启动它的Activity的任务栈中,而ApplicationContext是没有任务栈的。要解决问题,可以给待启动的Activity指定一个FLAG_ACTIVITY_NEW_TASK标记位,这样相当于是以SingleTask的方式启动的。
(2)singleTop: 栈顶复用模式。当栈顶和待创建的活动是一个实例的时候不会创建。
(3)singleTask:栈内复用模式,首先系统会检查待创建的活动要进入的栈是否存在,不存在就创建任务栈并进入,如果存在,那么再检查任务栈中是否有相同的实例,如果没有,那么直接进入,如果有,那么会清除该实例上面所有的活动,即clearTop效果。
(4)singleInstance:是加强的singleTask,不同的是它只有一个栈。
TaskAffinity
TaskAffinity和singleTask配对使用的时候,TaskAffinity指定的是Activity将要进入的任务栈。
TaskAffinity和allowTaskReparenting配合使用的时候,allowTaskReparenting为true,如果A应用调用B活动,但是B活动属于C应用,由于B活动的TaskAffinity值在C应用中,因此会产生自己的任务栈,这时候系统发现任务栈已经在A中被创建了,于是就把B从A的任务栈移到C中。
指定启动模式的方式
(1) 在AndroidManifest.xml的Activity标签中指定
(2) 在intent中的标志位指定。
IntentFilter的匹配规则
(1) action区分大小写,系统预定义了一些action,一个规则里面可以有多个action,只要满足其中一个Action就能满足要求。
(2) category可以不指定,不指定就匹配android.intent.category.DEFAULT,不管intent指定了几个category,每个都要和category中的任何一个相同。
(3) data主要由两部分构成,mimeType和URI,mimeType指的是媒体类型。URI的格式为<scheme>://<host>:<port>/ [<path>|<pathPrefix>|<pathPattern>]
,要指定完整指定data,必须调用setDataAndType,不然Data和Type会相互覆盖。
当我们用隐式的方式启动Activity的时候,需要判断是否有Activity满足要求,可以用PackageManager的resolveActivity或者Intent的resolveActivity的方法来判断,找不到就会返回null。
public abstract List<ResolveInfo> queryIntentActivities(Intent intent,int flags)
第二个参数flag一般指定为android.intent.category.DEFAULT,这样找到的Activity一定能够启动。