[TOC]
Activity
生命周期
您还可以使用 onPause() 方法释放系统资源、传感器(例如 GPS)手柄,或当您的 Activity 暂停且用户不需要它们时仍然可能影响电池续航时间的任何资源。
然而,正如上文的 onResume() 部分所述,如果处于多窗口模式,“已暂停”的 Activity 仍完全可见。因此,您应该考虑使用 onStop() 而非 onPause() 来完全释放或调整与界面相关的资源和操作,以便更好地支持多窗口模式。
onPause() 执行非常简单,而且不一定要有足够的时间来执行保存操作。因此,您不应使用 onPause() 来保存应用或用户数据、进行网络调用或执行数据库事务。因为在该方法完成之前,此类工作可能无法完成。相反,您应在 onStop() 期间执行高负载的关闭操作。
在 onStop() 方法中,应用应释放或调整在应用对用户不可见时的无用资源。例如,应用可以暂停动画效果,或从精确位置更新切换到粗略位置更新。 您还应使用 onStop() 执行 CPU 相对密集的关闭操作。例如,如果您无法找到更合适的时机来将信息保存到数据库,
- 从整个生命周期来说,onCreate和onDestroy是配对的,标志Activity的创建和销毁,并且只有一次调用,onStart和onStop是配对的,标志Activity是否可见,onResume和onPause是配对的,标志Activity是否在前台
- 前Activity的onPause执行完,新Activity的onResume才会执行 eg: (A)onPause -> (B)onCreate -> (B)onStart-> (B)onResume->(A)onStop
启动模式
- standard
- singleTop
- singleTask
- singleInstance
- 全局单例模式
- 会创建一个单独的任务栈,TaskRecord并且这个任务栈只有这一个单例,那次再启动会调用onNewIntent
任务栈
TaskAffinity
需要配合singleTask使用,或者singleInstance,经过试验,standard是不起作用的 在任务列表中会有单独的选项,并且将根页面的任务划走,新的taskAffinity的任务仍旧会存在。
allowTaskReparenting
在这种情况下,一旦和 Activity 有亲和性的任务进入前台运行,Activity 就可从其启动的任务转移到该任务。 举例来说,假设一款旅行应用中定义了一个报告特定城市天气状况的 Activity。该 Activity 与同一应用中的其他 Activity 具有相同的亲和性(默认应用亲和性),并通过此属性支持重新归属。当您的某个 Activity 启动该天气预报 Activity 时,该天气预报 Activity 最初会和您的 Activity 同属于一个任务。不过,当旅行应用的任务进入前台运行时,该天气预报 Activity 就会被重新分配给该任务并显示在其中。
当下一次将启动 Activity 的任务转至前台时,Activity 是否能从该任务转移至与其有相似性的任务 —“true”表示可以转移,“false”表示仍须留在启动它的任务处。 如果未设置该属性,则对 Activity 应用由 元素的相应 allowTaskReparenting 属性所设置的值。默认值为“false”。
正常情况下,Activity 启动时会与启动它的任务关联,并在其整个生命周期中一直留在该任务处。当不再显示现有任务时,您可以使用该属性强制 Activity 将其父项更改为与其有相似性的任务。该属性通常用于将应用的 Activity 转移至与该应用关联的主任务。
例如,如果电子邮件消息包含网页链接,则点击该链接会调出可显示该网页的 Activity。该 Activity 由浏览器应用定义,但作为电子邮件任务的一部分启动。如果将该 Activity 的父项更改为浏览器任务,则它会在浏览器下一次转至前台时显示,在电子邮件任务再次转至前台时消失。
Activity 的相似性由 taskAffinity 属性定义。通过读取任务根 Activity 的相似性即可确定任务的相似性。因此,按照定义,根 Activity 始终位于具有同一相似性的任务中。由于具有“singleTask”或“singleInstance”启动模式的 Activity 只能位于任务的根,因此更改父项仅限于“standard”和“singleTop”模式。(另请参阅 launchMode 属性。)
例子
1.应用A 通过隐式调用打开 应用B的 一个Activity,这个Activity设置为android:allowTaskReparenting="true"
2.例如 同一个应用的A、B、C 三个Activity。A、B没有指定TaskAffinity,C指定了TaskAffinity和SingleTask
A 启动 C , C启动 B, B启动C
假设B设置allowTaskReparenting,(true),那么A和B在同一个任务栈,C在自己的任务栈,查看最近任务,有两个任务栈,选择A的任务栈,点击返回能够正常回退入栈的B,切换C的任务栈,点击返回,回到桌面
假设B设置allowTaskReparenting(false),那么B和启动他的Activity在一个任务栈,这个时候B和C在同一个任务栈中。
android:resizeableActivity="true"
支持多窗口
android:clearTaskOnLaunch="true"
在根Activity设置,回到桌面再回到App,之前打开的页面消失
Flag
- FLAG_ACTIVITY_NEW_TASK
- FLAG_ACTIVITY_SINGLE_TOP
- FLAG_ACTIVITY_CLEAR_TOP
- FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- 不会出现在历史列表中了,比如A启动B,B设置了TaskAffinity和SingleTask,正常应该在最近任务列表看到B的单独的任务栈,如果Intent设置了FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,就不会看到B的单独的任务栈了。
异常状态
系统会调用onSaveInstanceState来保存当前Activity的状态。这个方法的调用时机是在onStop之前,它和onPause没有既定的时序关系,它既可能在onPause之前调用,也可能在onPause之后调用。
从时序上来说,onRestoreInstanceState的调用时机在onStart之后
关于保存和恢复View层次结构,系统的工作流程是这样的:首先Activity被意外终止时,Activity会调用onSaveInstanceState去保存数据,然后Activity会委托Window去保存数据,接着Window再委托它上面 的顶级容器去保存数据。顶层容器是一个ViewGroup,一般来说它很可能是DecorView。最后顶层容器再去一一通知它的子元素来保存数据,这样整个数据保存过程就完成了。可以发现,这是一种典型的 委托思想
onSaveInstanceState 调用时机
不是用户主动退出某个Activity,或者跳转到其他Activity时会触发
- 当用户按下Home键时
- 长按Home键,选择运行其他的程序时
- 按下电源键关闭屏幕时
- 从Activity A 中启动新的Activity时
- 屏幕方向切换时
- 电话打入等情况