开发艺术之旅 | Activity使用详解
生命周期
生命周期 | 状态 | 工作 |
---|---|---|
onCreate | Activity正在被创建 | 可以做一些初始化工作 |
onRestart | Activity从不可见重新变成可见 | |
onStart | Activity正在被启动,“可见”但不在前台 | |
onResume | Activity可见并且出现在前台,可交互 | |
onPause | Activity正在停止,接下来一般会调用onStop | 存储工作、停止动画,非耗时操作 |
onStop | Activity即将停止 | 稍微重量级的回收操作,不能太耗时 |
onDestroy | 即将被销毁 | 回收对象,释放资源 |
几种情况
- 打开新的Activity或者回到桌面 onPause -> onStop
- 回到原Activity onRestart -> onStart -> onResume
- 按back键回退 onPause -> onStop -> onDestroy
- 打开新的活动:旧的活动先执行 onPause方法,新的活动才会启动,执行顺序:onPause -> onCreate -> onStart -> onResume -> (First Activity) onStop 所以不能再onPause执行耗时操作,需要让新的Activity尽快显示出来
成对的生命周期
- 从整个生命周期来看:onCreate 和 onDestroy 标注Activity的创建和销毁
- 从Activity是否可见来看:onStart 和 onStop 可能会被调用多次
- 从Activity是否在前台:onResume 和 onPause
onStart和onResume、onPause 和 onStop 的区别
角度不同 如上;实际使用无明显区别
异常情况下生命周期分析
- onSaveInstanceState() :存储数据 在 onStop 方法之前调用
- onRestoreInstanceState() :恢复数据 在onStart 方法之后调用
情况一:资源相关的系统配置发生改变
默认情况下Activity会被销毁并重新创建
onSaveInstanceState -> onDestroy/onCreate(new) -> onRestoreInstanceState
系统帮我们做了一定的恢复工作,例如文本框输入的数据、滑动位置等和View相关的状态
- onRestoreInstanceState:Activity被销毁并且重新创建才会调用 里面的Bundle一定不为空
委托思想
每个view都有上述两个方法
- Activity -> onSaveInstanceState 保存数据
- Activity 委托 Window保存数据
- Window 委屈上面的顶级容器保存数据(Viewgroup,一般来说是DecorView)
- 顶层容器一一通知它的子元素保存数据
情况二:资源内存不足导致低优先级的Activity被杀死
优先级:
- 前台Activity
- 可见但非前台的Activity——例如打开了一个Dialog
- 后台Activity——已经被暂停的Activity,执行力onStop
如何在系统配置改变时不重新创建Activity?
AndroidMainifest中,activity标签有个字段:configChanges 可以定义,指定多个标签用“|”连接。
常用标签:
- locale: 设备的本地位置发生了改变,一般为切换了系统语言
- orientation: 屏幕方向发生了改变
- keyboardHidden: 键盘的可访问性发生了改变,例如用户调出了键盘
需要注意的标签:
- screenSize: 屏幕的尺寸信息发生了改变
- smallestScreenSize: 设备的物理尺寸发生改变,例如切换了外部显示设备
当这两个标签在API小于13时,此选项不会导致Activity重启,否则会;因此在常用防止Activity进行重启需加入:
android:configChanges="orientation|screenSize"
加入后改变屏幕的方向就不会Activity就不会重启了
Activity的启动模式
- standard
- singleTop
- singleTask
- singleInstance
standard
标准模式,每次都会创建一个新的实例,并进入启动它的Activity的栈中;如果是由非Activity的context启动的(例如ApplicationContext),其并没有任务栈,因此会报错误,所以需要加上FLAG_ACTIVITY_NEW_TASK标记位,此时Activity实际上是以singleTask模式启动的
singleTop
栈顶复用,如果已经处于任务栈的栈顶,就不会重新创建这个Activity,而是会回调onNewIntent()方法【不会调用onCreate、onStart方法】
singleTask
栈内复用
如果在目标任务栈中存在Activity的实例,则不会创建一个新的Activity,而是将这个实例移到栈顶并将上面所有的Activity出栈,并回调onNewIntent()方法【不会调用onCreate、onStart方法】;
- 如果目标任务栈不存在(跨应用调用),会先创建目标栈
- 在目标任务栈中寻找实例,如果不存在,则创建实例并压入栈中,如果存在,则调到栈顶
singleInstance
单实例模式
具有singleTask所有的特性,但是只能位于一个单独的任务栈中,后续调用都会启动这个栈中实例,除非任务栈被销毁
Activity的Flag
可以通过设定Flag设定启动模式,常见的几个Flag:
- FLAG_ACTIVITY_NEW_TASK 指定为singleTask模式
- FLAG_ACTIVITY_CLEAR_TOP 清空同一个任务栈中所有的Activity,一般配合NEW_TASK 一起使用
- FLAG_ACTIVITY_SINGLE_TOP 指定为single_top模式
- FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 不会出现在历史Activity的列表中
隐式启动Activity(IntentFilter)
隐式启动必须匹配过滤列表中所有的种类,一个Activity可以有多组IntentFilter
- action 字符串,区分大小写,如果有多个,只要匹配其中一个就可以
- category 字符串,可以不指定,但是指定了就必须能匹配到,才能启动
- data 由 mimeType 和 URI组成;mimeType 指媒体类型(image/jpeg、audio/mpeg4-generic、video/*)匹配时通过intent.setDataAndType(Uri data, String type)方法对date进行设置。