icode icode
首页
  • Android学习

    • 📁基础内容
    • 📺AndroidCore
    • 🎨Android-UI
    • 🏖️Components
    • 📊Fragment
    • 🔗网络操作
    • 🔏异步机制
    • 📦数据存储
    • 🗃️Gradle
  • 学习笔记

    • 『框架』笔记
    • 『Kotlin』笔记
    • 《Vue》笔记
    • 《Git》学习笔记
    • 『Bug踩坑记录』
  • ListView
  • RecyclerView
  • ViewPager
  • Java笔记

    • 🟠JavaSE
    • 🟢JavaWeb
    • 🔴JavaEE
    • ⚪JavaTopic
    • 🍳设计模式
  • 计算机基础

    • 📌计算机网络
    • 🔍数据结构
    • 📦数据库
    • 💻OS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
  • 关于

    • 📫关于我
  • 收藏

    • 网站
    • 资源
    • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

iqqcode

保持对技术的探索实践与热爱
首页
  • Android学习

    • 📁基础内容
    • 📺AndroidCore
    • 🎨Android-UI
    • 🏖️Components
    • 📊Fragment
    • 🔗网络操作
    • 🔏异步机制
    • 📦数据存储
    • 🗃️Gradle
  • 学习笔记

    • 『框架』笔记
    • 『Kotlin』笔记
    • 《Vue》笔记
    • 《Git》学习笔记
    • 『Bug踩坑记录』
  • ListView
  • RecyclerView
  • ViewPager
  • Java笔记

    • 🟠JavaSE
    • 🟢JavaWeb
    • 🔴JavaEE
    • ⚪JavaTopic
    • 🍳设计模式
  • 计算机基础

    • 📌计算机网络
    • 🔍数据结构
    • 📦数据库
    • 💻OS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
  • 关于

    • 📫关于我
  • 收藏

    • 网站
    • 资源
    • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 基础内容

  • AndroidCore

    • Activity

      • Activity概况
      • Activity基础
      • Button点击事件的几种实现方式
      • Activity之间的跳转
      • 一个APP拉起另一个APP
      • Activity其他属性
      • Activity启动模式
        • 1. Task与Back-Stack
          • Back-Stack
          • 【小结】
        • 2. Activity的LaunchMode
          • 2.0 Activity的4种launchMode
          • 2.1 standard
          • 2.2 singleTop
          • 2.3 singleTask
          • taskAffinity
          • 2.4 singleInstance
        • 3. 激活Activity与压栈
          • 3.1 保存Activity的状态
          • 3.2 Activity的销毁与出栈
          • 3.3 Activity的状态与Back Stack
      • Activity生命周期
      • Activity 是被压入后台,还是跳转到新的 Activity
      • Activity其他操作
    • BroadcastReceiver

    • ContentProvider

    • Android-Service

    • Intent

  • Android UI

  • Components

  • Fragment

  • 网络操作

  • 异步机制

  • 数据存储

  • 学习笔记

  • 自定义View

  • View事件体系

  • Android
  • AndroidCore
  • Activity
iqqcode
2021-04-27
目录

Activity启动模式

6040

声明启动模式有两种方式:

  1. 在清单文件中声明待启动的 Activity 的 launchMode 属性
  2. 代码中通过 Intent 启动 Activity 时,设置 flag

如果在一次启动过程中,两种方案都设置了,后者优先级比较高。清单文件的 launchMode 和 intent flag 都不能完全代替对方。

# 1. Task与Back-Stack

Task表示“作业”或“任务”,充当Activity的容器,Task使用Back-Stack保存管理各个Activity。在Android系统中,执行某个任务时可能存在多个与用户产生交互的Activity,Task则是这些Activity的容器。

(1) 执行Task的多个Activity不一定属于同一个应用程序

  • 例如:A程序的Activity输入邮件内容,B程序的Activity来发送邮件

(2) 执行Task的多个Activity中,可能有同一个Activity的多个实例

  • 例如:MainActivity也可以激活自身,而且可以反复操作,可能存在多个MainActivity的实例

# Back-Stack

Back-Stack表示“回退栈”,每个Back-Stack栈顶得Activity被置于前台,称之为Foreground Avtivity(前台Activity),遵循栈的规则

我们新打开的Activity,由于是由Task来管理的,都是存储在了Back-Stack之中;所以新的Activity是覆盖到了旧的Activity之上,显示的是当前处在栈顶的 Foreground-Activity

image-20210303112115158

  • 在Android中,系统用Task Stack(Back Stack)结构来存储管理启动的Activity对象

  • 一个应用启动,系统就会为其创建一个对应的Task Stack来存储并管理该应用的Activity对象

  • 只有最上面的任务栈的栈顶的Activity才能显示在窗口中

这也符合我们看到的界面结构,新出现的Activity总是覆盖在之前的Activity之上,按返回键则回退至上一个Activity

# 【小结】

  • Task作为一个容器,使用Back-Stack保存、管理Activity
  • 用户在使用Android时,可以启动多个Task
  • 每个Task都是有聚合力的单元,它可以在用户启动一个新的Task或按下Home键时整体的被置于后台
  • 无论Task是被置于前台还是后台,Back-Stack都是完整的保存。因此,用户在执行某个Task时,另外启动了新的Task,则原Task被置于后台;但当原Task重新置于前台时,它的Back Stack依然存在。

🚀就像我在用手机刷知乎,突然此时来了电话,那么被打开的知乎的ZHActivity就会被电话PhoneActivity覆盖。此时PhoneActivity位于前台栈顶,在Back-Stack中ZHActivity位于其下面。当我挂了电话之后,此时ZHActivity又回到了栈顶位置。

具体是回到知乎的首页、消息、我的的哪个Activity,要根据之前谁处在Back-Stack上面的位置,这都是被记录好了的




# 2. Activity的LaunchMode

📺扔物线-当我按下 Home 键再切回来,会发生什么 (opens new window)

LounchMode为启动模式,Activity的launchmode被配置为不同的值时,当尝试激活Activity时可能会受影响:

  • 该Activity的实例数量不同
  • 所在的Task不同(在Activity中通过getTaskId查看Task的ID)
  • 在Back-Stack中的列表不同
  • 在Back-Stack中各Activity经历的生命周期不同

在AndroidManifest中配置:

image-20210303113521681

# 2.0 Activity的4种launchMode

standard 标准模式

  • 标准模式,每次激活Activity时均在当前任务栈中创建新的实例(每次均创建新的实例)

singleTop 栈顶时唯一

  • 位于栈顶时唯一:如果当前Activity已位于当前任务栈栈顶,则不会创新的实例

singleTask 独立于任务栈

  • 独立于任务栈,如果该Activity的实例不存在,创建并且获得栈顶位置;如果实例已存在,则将其上方的Activity均出栈,且该Activity获得栈顶位置

singleInstance 实例唯一

  • 实例唯一,实例独占任务栈,且无论哪个任务栈共享同一个Activity实例

# 2.1 standard

标准模式,每次激活Activity时均在当前任务栈中创建新的实例(每次均创建新的实例)

image-20210306110141187

# 2.2 singleTop

位于栈顶时唯一:如果当前Activity已位于当前任务栈栈顶,则不会创新的实例

  • 当前Activity不存在 或者 已存在且位于栈顶:不会创建新的实例
  • 待启动 Activity 已经位于源 Activity 所属的任务栈的栈顶时,不会创建新的 Activity,而是直接使用栈顶的 Activity,并回调它的 onNewIntent 方法,onCreate 和 onStart 不会被调用,直接回调 onResume

image-20210306110900606

  • 当前Activity存在且不位于栈顶:会创建新的实例位于栈顶

singleTop下,已位于栈顶则不会创建新的实例,否则均会创建新的Activity置于栈顶

image-20210306111545136

# 2.3 singleTask

全局单实例,首先会寻找要启动的 Activity 想要的任务栈(默认或者 taskAffinity 属性指定),如果没有找到,则创建新的任务栈并将 Activity 实例放入。如果找到了想要的任务栈,这时候要判断栈中是否已经存在该 Activity 的实例,如果已经存在,会将该 Activity 以上的其他 Activity 实例弹出,把自己放到栈顶,同样也是回调 onNewIntent 和 onResume。如果实例不存在,创建新的实例并压入栈中。

  • 独立于任务栈,如果该Activity的实例不存在,创建并且获得栈顶位置;

image-20210306112033398

  • 如果实例已存在,则将其上方的Activity均出栈(顶出去),且该Activity获得栈顶位置

image-20210306112643534

# taskAffinity

Affinity表示Activity的“亲属关系”。在AndroidManifest.xml文件中,可以为每个Activity配置taskAffinity属性,表示该Activity希望进入的Task,该属性的值是字符串。

image-20210306135846996

默认情况下,同一个应用程序中各个Activity的taskAffinity属性值均相同,则表示使用Application的taskAffinity,如果Application没有指定该属性,则默认为项目的包名。

在配置taskAffinity属性时,取值应参照包名的命名格式,且不应该使用下划线_,避免应用程序在编译打包时出现问题。

# singleTask与taskAffinity

image-20210306142814380

一个应用程序在运行,但是却启动了两个任务

【情景1】

  • SingleTaskActivity的launchMode配置为singleTask;
  • SingleTaskActivity与激活它的Activity有相同的taskAffinity(使用默认,或显式的指定相同属性值)。

结论:SingleTaskActivity与激活它的Activity在相同的Task中。

【情景2】

  • SingleTaskActivity的launchMode配置为singleTask;
  • SingleTaskActivity与激活它的Activity配置了不同的taskAffinity。

结论:SingleTaskActivity与激活它的Activity在不同的Task中。

【情景3】

两个不相同的应用程序启动,但是却公用一个相同的Task

  • SingleTaskActivity的launchMode配置为singleTask;使用另一个应用程序的Activity去激活SingleTaskActivity;
  • SingleTaskActivity与激活它的Activity配置了相同的taskAffinity。

结论:SingleTaskActivity与另一个应用程序中激活它的Activity在相同的Task中。

# 2.4 singleInstance

全局单实例,首次启动时会创建新的 Activity 实例,并放入一个新的任务栈中,且 这个任务栈中只会有这一个实例。 后续启动不会再新建实例。

image-20210306150019837

image-20210306145248089

SingleInstance与taskAffinity

由被配置为singleInstance的Activity激活的其它Activity,会尝试放在存在“亲属”关系的Task中,如果没有匹配的Task存在,则会创建新的Task存放被激活的Activity。

# 3. 激活Activity与压栈

当Activity被激活时,它在Back-Stack中压栈,成为栈顶Activity,被显示且获得焦点

第一次启动某个应用程序

大多数Task一Home界面或应用程序列表为界面作为起点,当用户点击程序icon时,Task被创建且置于前台。系统检测到入口Activity后在Back-Stack中压栈。由于Task是新创建的,此时Task中只有一个Activity(入口Activity即时栈顶也是栈底),所以入口Activity获得焦点

# 3.1 保存Activity的状态

当同一个Task中,出现新的Activity压栈时 或者 当前Task被真题置于后台时,原Task栈顶的Activity被停止时的状态被保存

在程序的登录界面中,输入了用户信息,被来电中断,通话结束后,原登录界面中已经输入的信息依然存在

注意:由于系统可能因为资源不是而销毁一些Activity,所以并不能保证当Task被置于后台之后,再次回到前台时Activity的状态依然存在,因为很可能整个Activity都已经不存在了。

# 3.2 Activity的销毁与出栈

当用户点击"Back"键时,栈顶的Activity出栈,一旦出栈,则该Activity被终止,且资源被回收,即销毁。

# 3.3 Activity的状态与Back Stack

在Back Stack中,Activity的状态可能为:

  • 当新激活的Activity压栈,则成为栈顶的Activity,该Activity处于运行态
  • 当用户点击“Back”键,栈顶Activity出栈,且被销毁,处于终止态
  • 在栈内,且处于栈顶的Activity,可能处于暂停(可见不可控)、停止态、终止态

image-20210306165612010

编辑 (opens new window)
#activity
上次更新: 2022/03/27, 22:58:50
Activity其他属性
Activity生命周期

← Activity其他属性 Activity生命周期→

最近更新
01
匿名内部类
10-08
02
函数式接口
10-08
03
ARouter-Kotlin踩坑
10-05
更多文章>
Theme by Vdoing | Copyright © 2021-2023 iqqcode | MIT License | 备案号-京ICP备2021028793号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×