美文网首页
Activity 生命周期+启动模式

Activity 生命周期+启动模式

作者: 海盗的帽子 | 来源:发表于2018-07-06 20:57 被阅读9次

    一.任务( Task )

    Android 系统是使用多任务机制的。 任务就是指在执行特定作业时与用户交互的一系列 Activity,在相同任务中的 Activity 有相同的标识( TaskAffinity ,默认情况下为包名 )因此通常情况下,一个应用中的 Activity 属于一个任务。 任务中的 Activity 按照各自的打开顺序排列在堆栈(即返回栈)中,也就是说每个任务有自己的返回栈。当用户点击应用图标的时候,如果这个应用的任务不存在(即未启动),就会创建一个新的任务,并将这个应用的指定的 MAIN Activity 实例化并压入栈中,如果这个应用的任务存在(已启动,但是在后台),就会将这个任务转换到前台。如果用户开始新的任务或者转到主屏幕的时候,旧任务中的所有 Activity 就会停止,但是这个任务的返回栈不变,仅仅是任务从前台转换到后台。
    后台可以同时运行多个任务。但是,如果用户同时运行多个后台任务,则系统可能会开始销毁后台 Activity,以回收内存资源,从而导致 Activity 状态丢失。

    二.返回栈(Back Stack)

    Android 是使用任务 (Task)来管理 Activity 的进出顺序,一个任务就是一组存放在栈里的 Activity 的集合,这种栈也称为返回栈,是一种后进先出的数据结构。
    · 当 Activity A 启动 Activity B 时,Activity A 将会停止,但系统会保留其状态, Activity B 就入栈并置于栈顶。如果用户在处于 Activity B 时按“返回”按钮,则 Activity A 将恢复其状态,继续执行,Activity B 就出栈 ,Activity A 重新回到栈顶。
    · 用户通过按“主页”按钮离开任务时,当前 Activity 将停止且其任务会进入后台。 系统将保留任务中每个 Activity 的状态。如果用户稍后通过选择开始任务的启动器图标来恢复任务,则任务将出现在前台并恢复执行堆栈顶部的 Activity。
    · 如果用户按“返回”按钮,则当前 Activity 会从堆栈弹出并被销毁。 堆栈中的前一个 Activity 恢复执行。销毁 Activity 时,系统不会保留该 Activity 的状态。
    · 即使来自其他任务,Activity 也可以多次实例化

    三.状态

    (一).运行状态

    处于栈顶,可见,面对着用户。

    (二).暂停状态

    可见但不是最前(比如出现对话框),只有在内存极低的情况下才会考虑回收这种 Activity。

    (三).停止状态

    不是栈顶且完全不可见,==保存着相应的状态和成员变量==,可能会被系统回收

    (四).销毁状态

    从栈中移除后,系统最可能回收这种 Activity。
    · 一个 Activity 如果处于暂时不可见的状态,系统会保留其状态,当重新可见,回到栈顶的时候系统就会对 Activity 进行恢复。如果系统回收了系统内存资源, Activity 可能会被完全销毁,这时系统仍然知道 Activity 在栈中,所以当这个 Activity 重新回到栈顶的时候就会重新创建 Activity 而不是进行恢复。

    四.生命周期

    (一).典型状态下

    image

    resume 的读音 [rɪ'zju:m]

    1.生存期

    完整的生存期:onCreate -> onDestory
    可见生存期:onStart -> onStop
    前台生存期:onResume -> onPause

    2..几点要注意的

    (1).当进程被 kill 掉后重新返回 Activity 后执行的是 onCreate
    (2).当Activity 重新回到栈顶,即重新回到这个 Activity 的时候 执行的是 onRestart -> onStart -> onResume
    (3).对一个特定的 Activity ,第一次启动时 onCreate->onStart -> onResume
    (4).当用户打开一个新的 Activity 或者切换到桌面的时候,执行的是onPause-> onStop
    (5).onStart -> onStop 是从 Activity 是否可见这个角度来回调的,onResume -> onPause 是从 Activity 是否位于前台这个角度来回调的。
    (6).Activity A 启动 Activity B 时,A 的 onPause 先执行,B 的 onResume 后执行。因此尽量在 onStop中尽量操作而不要在 onPause ,从而使新的 Activity 能够尽快显示。

    (二).异常状态下

    1.资源相关的系统配置发生改变导致 Activity 被 kill 并重新创建
    2.资源内存不足导致低优先级的 Activity 被 kill
    在异常情况下,系统会调用 onSaveInstanceState 保存当前的状态,这个方法是在 onStop 之前,在正常情况下系统不会调用这个方法,在 Activity 被重新创建之后 系统会调用 onRestoreInstance 并且把 onSaveInstanceState 保存的 Bundle 对象作为参数传递给 onRestoreInstance 和 onCreate .
    注意:和 Activity 一样, 每个 View 也有 onSaveInstanceState 和 onRestoreInstance ,保存和恢复 View 的层次结构的过程是:首先 Activity 被意外终止时,Activity 会调用 onSaveInstanceState 去保存数据,然后 Activity 委托 Window 去保存数据,接着 Window 会委托顶级容器去保存数据,然后顶级容器再去一一通知它的子元素去保存数据。
    onRestoreInstance 一旦被调用 Bundle 的值就不为 null, 而 onCreate 的 Bundle 不一定有值。

    五.启动模式

    启动模式允许定义 Activity 的实例如何与当前任务进行关联,有两种方式:
    1.使用清单文件( launchMode )
    2.使用 Intent 标志( Flag )

    (一).TaskAffinity

    affinity 的读音:[əˈfɪnɪti]

    taskAffinity 就是任务关联属性,或者说是在 任务中的 Activity 有一个标识, 拥有相同的 taskAffinity 的 Activity 理论上属于相同 任务。任务的 taskAffinity 是由它的根 Activity 决定的。应用程序默认的 taskAffinity 的名字是 <manifest> 元素中设定的 package 名。默认下,一个应用程序中的所有 Activity 都拥有相同的 affinity 。通过设置可以进行修改,甚至可以把不同应用程序中定义的 Activity 放置到相同的 任务中。在两种情况下这个关联会起作用:
    1.启动 Activity 的 Intent 包含 FLAG_ACTIVITY_NEW_TASK 标志 ,或者和 singleTask 启动模式配对使用.
    2.Activity 将其 allowTaskReparenting 属性设置为 true
    假设有应用 A 启动 应用 B 的 Activity ,这个 Activity 的 allowTaskReparenting 设置为 true,那么就会重新创建一个新的任务栈并且将这个 Activity 入栈,这个属性的作用是,如果这个时候启动 应用B ,则 B 将使用原来已经创建的任务栈,且这个时候不会启动 应用 B 的 MAIN Activity ,而是直接显示已经启动的 Activity 。

    (二).launchMode

    1.Standard 是 Activity 的默认的启动模式,系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,在不同任务中都可以创建这个 Activity ,并且一个任务可以拥有多个实例 在这种模式下,每次启动 Activity 都会重新创建一个新的实例置于栈的顶端。注意在默认情况下,这个 Activity 会置于 启动 Activity 的任务栈中,这与 TaskAffinity 的值无关。

    standard 的读音 [ˈstændərd]

    2.SingleTop 在这种模式下如果启动的 Activity 已经在栈顶就不再创建新的活动,系统会通过调用该实例的 onNewIntent() 方法向其传送 Intent,而不是创建 Activity 的新实例. 如果不是在栈顶就仍然重新创建一个。同样的, Activity 可以多次实例化,且每个实例可以属于不同的任务,并且一个任务可以有多个实例(前提是在启动时栈顶的 Activity 不是目标 Activity )。需要注意的是 Activity 的 onCreate ,onStart 不会执行。
    当 Activity 的现有实例处理新 Intent 时,则在新 Intent 到达 onNewIntent() 之前,用户无法按“返回”按钮返回到 Activity 的状态。
    3.SingleTask 在这种模式下如果这个 Activity 不存在,系统就会创建新任务并实例化位于新任务底部的 Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的 onNewIntent() 方法向其传送 Intent,而不是创建新实例即一次只能存在 Activity 的一个实例。 启动的 Activity 如果在栈中已经存在,不管实在栈顶还是在栈内,都会直接使用栈中的实例,并且将栈中这个 Activity 之上的 Activity出栈使得这个 Activity 在栈顶。如果启动指定 singleTask 启动模式的 Activity,则当某后台任务中存在该 Activity 的实例时,整个任务都会转移到前台,并且压入当前任务的返回栈。此时,返回栈包括上移到堆栈顶部的任务中的所有 Activity 。
    举几个例子:
    (1).如果启动的 Activity 的 taskAffinity 和当前任务栈不一样,就创建新的任务栈。
    (2).如果任务栈一样并且没有这个实例就创建实例直接入栈
    (3).如果任务栈一样且有这个实例就将实例 Activity 置于栈顶
    尽管 Activity 在新任务中启动,但是用户按“返回”按钮仍会返回到前一个 Activity。
    需要注意:

    如上图,YX 是后台任务栈(都用 singleTask 指定模式)中,启动 Y 后,后台任务栈会添加到前台,如果启动的是X ,那么Y 首先会出栈然后 X 会治愈前台的任务栈中。

    4.SingleInstance 在这种模式下,系统不会将任何其他 Activity 启动到包含实例的任务中。该 Activity 始终是其任务唯一仅有的成员。 启动 Activity 会重新创建一个返回栈来管理这个 Activity,这种模式常用在不同的应用进程访问同一个 Activity的情况。

    (三).Flag

    在启动 Activity 时,可以通过传递给 startActivity() 的 Intent 中加入相应的标志,修改 Activity 与其任务的默认关系。
    1.FLAG_ACTIVITY_NEW_TASK:这与前面的 singleTask 是相同的行为
    2.FLAG_ACTIVITY_CLEAR_TOP:这与之前的 singleTop 是相同的行为
    3. FLAG_ACTIVITY_CLEAR_TOP:如果正在启动的 Activity 已在当前任务中运行,则会销毁当前任务顶部的所有 Activity,并通过 onNewIntent() 将此 Intent 传递给 Activity 已恢复的实例(现在位于顶部),而不是启动该 Activity 的新实例.
    4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:这个属性对应 android:excludeFromRecents=“true”,设置这个属性后,只要 A 不在前台了, 那么系统会将A所处的任务栈从多任务管理器中移除,因此和 A 属于同一 任务栈的 Activity 也会被从任务管理中消除,如果不是在同一任务栈,那么只能看到 B 的任务栈,不能看到 A 的 。
    5.FLAG_ACTIVITY_BROUGHT_TO_FRONT:设置这个模式后,如果栈中有这个实例,那么就将这个实例提到栈顶,比如 B 设置了这个标志,现在有 A-B-C-D, D 启动 B 后,就会变成 A-C-D-B.
    6.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY:这个标志一般不由应用程序代码设置,如果这个Activity是从历史记录里启动的(常按HOME键)
    7.FLAG_ACTIVITY_CLEAR_TASK:此Activity将变成一个新Task中新的最底端的Activity,所有的之前此Activity实例和包含该实例的Task都会被关闭,这个标识仅仅和FLAG_ACTIVITY_NEW_TASK联合起来才能使用。
    如果指定 Activity 的启动模式为 "standard“ ,这时使用该标志时,这个 Activity 也会从堆栈中移除,并在其位置启动一个新实例,以便处理传入的 Intent。 这是因为当启动模式为 ”standard" 时,将始终为新 Intent 创建新实例 ,这就是说如果 启动的 Activity 是 standard 模式,那个这个 Activity 和这个 Activity 之上的 Activity 都出栈,然后重新创建一个新的实例入栈。singleTask 就默认有这个标记位的效果。

    (四).区别

    从优先级来看,设置 Flag 的优先级要高于 指定launchMode ,当两种同时存在的时候以第二种方式为准。同时两种方式也有另一种方式不能实现的模式。

    六.清理返回栈

    如果用户长时间离开任务栈,系统会清除任务的所有 Activity ,除了根 Activity 除外,当用户再次返回时,仅仅恢复根 Activity ,这样做是为了在经过长时间后,用户已经放弃了之前的操作,返回任务是要进行新的操作。
    1. alwaysRetainTaskState :如果在任务的根 Activity 中将此属性设置为 true,在很长一段时间后,任务仍将所有 Activity 保留在其堆栈中 。
    2. clearTaskOnLaunch :如果在任务的根 Activity 中将此属性设置为 true ,则每当用户离开任务然后返回时,系统都会将堆栈清除到只剩下根 Activity。 即使只离开任务片刻时间,用户也始终会返回到任务的初始状态。
    3. finishOnTaskLaunch : 与 clearTaskOnLaunch 相似,但是对单个 Activity 起作用,而不是整个任务。Activity 仍是任务的一部分,但是仅限于当前会话。如果用户离开然后返回任务,则任务将不复存在 。

    七.启动任务

    通过为 Activity 提供一个以 "android.intent.action.MAIN" 为指定操作;以 "android.intent.category.LAUNCHER" 为指定类别的 Intent 过滤器,可以将 Activity 设置为任务的入口点,此类 Intent 过滤器会使 Activity 的图标和标签显示在应用启动器中(就是按 Home 键弹出的 应用界面),让用户能够启动 Activity 并在启动之后随时返回到创建的任务中。

    相关文章

      网友评论

          本文标题:Activity 生命周期+启动模式

          本文链接:https://www.haomeiwen.com/subject/ewobuftx.html