前言,本篇文章主要用于自己梳理知识,所谓”千金难买回头看”,定期复习知识点很有必要。参考,其一:一位非常厉害的妹子写的Activity总结,其二:刚哥的《Android开发艺术探索》,当然,妹子的总结也是来源于刚哥的书。该博主学习和总结能力远在我之上,她的总结很具有参考价值,若涉及到侵权问题,请及时告知,会立刻删除。联系方式:yucrun@163.com
一.Activity生命周期
1.典型情况的生命周期
a.正常情况下Activity经历的生命周期
- onCreate()
- 状态:表示Activity正在创建;
- 任务:可调用setContentView方法去加载布局和一些初始化工作;
- onRestart()
- 状态:表示activity正在重新启动。
- 调用时机:当前activity由不可见转换为可见时会被调用;
- onStart():
- 状态:表示activity正在被启动;
- 特点:可见,但activity在后台,不可以与用户交互;
- onResum():
- 状态:表示activity已经可见;
- 特点:可见,在前台,activity在活动;
- onPause():
- 状态:表示activity正在停止;
- 特点:正常情况下,会立刻调用onStop方法。在该方法内可执行一些不太耗时的任务,存储数据,停止动画等;
- onStop():
- 状态:表示activity即将停止;
- 特点:在方法内可以做重量级回收工作,同样,不能过于耗时;
onDestroy()
前者是从Activity是否可见这个角度来回调的;
-
c.假设当前Activity为A,这时如果用户打开一个新Activity B,那么B的onResume和A的onPause哪个先调用
先说答案:A的onPause方法先于B的onResume方法调用;
- 简单理解activity的启动过程
- 1.启动Activity的请求由instrumentation来处理;
- 2.instrumentation通过Binder向AMS发请求;
- AMS内部维护一个ActivityStack,ActivityStack负责栈内的Activity的状态同步
- 3.AMS通过ActivityThread去同步Activity的状态从而完成生命周期方法的调用
- 4.问题d的答案在ActivityStack中的resumeTopActivityInnerLocked方法中可以找到注释说明
- We need to start pausing the current activity so the top one can be resumed…
- We need to start pausing the current activity so the top one can be resumed…
d.Activity生命周期的切换过程
- 针对特定的Activity A,第一次启动,回调如下:onCreate —> onStart —> onResume。
- 在Activity A中启动Activity B,回调如下,A的onPause —> B的onCreate —> onStart —> onResume —> A的onStop(如果B为透明主题,则不回调该方法)
- 关闭屏幕或者Home键
- B的onPause —>onStop —> A的onStop(如果B为透明主题或对话框Activity,则回调该方法)
- 点亮屏幕/回到前台
- B的onRestart()—>onStart()—>A的onRestart()—>onStart()—>B的onResume()
关闭B
onSavaInstanceState:系统异常终止时,保存当前Activity的状态;
- 该方法调用在onStop之前,但和onPause没有时序关系;
- onSaveInstanceState与onPause的区别:前者适用于对临时性状态的保存,而后者适用于对数据的持久化保存;
- 正常情况下,系统不会回调这个方法;
- Activity被重建后,调用该方法,并且把onSavaInstanceState保存的Bundle对象作为参数同时传递给onRestoreInstanceState与onCreate方法。因此,可以通过onRestoreInstanceState与onCreate方法来判断activity是否被重建了;
- onRestoreInstanceState:Activity被重建后,会调用该方法;
- 谷歌更推荐使用onRestoreInstanceState进行数据恢复;
- 从时序上来说,onRestoreInstanceState的调用时机在onStart之后;
- 在onSavaInstanceState和onRestoreInstanceState方法中系统为我们做了一定的恢复工作,每一个View中都有这两个方法。关于保存和恢复View的层次结构,系统的工作流程是:
- Activity去调用onSavaInstanceState方法去保存数据;
- 然后Activity会去委托Window去保存数据;
- 接着,Window会去委托它上面的顶层容器去保存数据,顶层是一个ViewGroup(一般来说很有可能是DecorView);
- 最后,顶层容器去通知它的子元素来保存数据;
- 综上:整个数据保存的过程就完成了,这是一种典型的委托思想,像View的绘制过程,事件分发都是采用类似的思想;
由于配置改变导致Activity重建的问题可以避免,通过在AndroidManifest.xml中对应的Activity中设置android:configChanges=”orientation|screenSize”。
b.资源不足导致低优先级的Activity被杀死
Activity优先级排序
- 前台可见Activity>前台可见不可交互Activity(前台Activity弹出Dialog)>后台Activity(用户按下Home键、切换到其他应用)
- 当系统内存不足时,会按照Activity优先级从低到高去杀死目标Activity所在的进程;
若一个进程没有四大组件在执行,那么这个进程将很快被系统杀死;
二.Activity四种启动模式
1.standard:标准模式
-
2.singleTop:栈顶复用模式
这种模式下,如果新的activity在任务栈的栈顶,那么此activity就不会被重新创建。同时,它的onNewIntent方法会被回调,此方法的参数可以取出当前请求的信息;
3.singleTask:栈内复用模式
栈内复用,这是一种单实例,只要activity在一个栈中存在,那么多次创建该activity都不会重新创建实例。同时,会回调onNewIntent方法。以及,clearTop效果。
4.singleInstance:单实例模式
具有singleTask的所有特定,另外,该模式的Activity只能单独地位于一个任务栈中。
5.注意:
5.1.可以通过标记位来指定启动模式或者通过launchMode设置启动模式。
- FLAG_ACTIVITY_SINGLE_TOP:对应singleTop启动模式;
- FLAG_ACTIVITY_NEW_TASK :对应singleTask模式。;
- 5.2.非activity类型的Context并没有所谓的任务栈,解决这个问题的是为待启动的activity指定FLAG_ACTIVITY_NEW_TASK标记位;
- 5.3.TaskAffinity:对应任务栈的名字,任务栈名称默认是应用程序的包名。
三.IntentFilter匹配规则
原则: ①一个intent只有同时匹配某个Activity的intent-filter中的action、category、data才算完全匹配,才能启动该Activity。 ② 一个Activity可以有多个 intent-filter,一个 intent只要成功匹配任意一组 intent-filter,就可以启动该Activity。
1.action匹配规则
- 要求intent中的action 存在且必须和intent-filter中的其中一个 action相同。
-
2.category匹配规则
intent中的category可以不存在,这是因为此时系统给该Activity 默认加上了< category android:name=”android.intent.category.DEAFAULT” />属性值。
除上述情况外,有其他category,则要求intent中的category和intent-filter中的所有category 相同。
3.data匹配规则
如果intent-filter中有定义data,那么Intent中也必须也要定义date。
- data主要由mimeType(媒体类型)和URI组成。在匹配时通过intent.setDataAndType(Uri data, String type)方法对date进行设置。
采用隐式方式启动Activity时,可以用PackageManager的resolveActivity方法或者Intent的resolveActivity方法判断是否有Activity匹配该隐式Intent。