当前位置: 首页 > news >正文

【Android】Activity 的生命周期和启动模式

目录

Activity 生命周期

具体场景

  Activity 的首次启动

  用户打开新的 Activity 或返回桌面

  用户回到 Activity

异常情况

  资源相关的系统配置发生改变导致 Activity 被杀死并重新创建

  资源内存不足导致低优先级的 Activity 被杀死

Activity LaunchMode

  standard 标准模式

  singleTop 栈顶复用模式

  singleTask 栈内复用模式

  singleInstance 单实例模式

  allowTaskReparenting 属性

  指定启动模式

Flags 标志位

IntentFilter 过滤规则

  action 的匹配规则

  category 的匹配规则

  data 的匹配规则

  匹配判断


Activity 生命周期

  Activity 生命周期回调方法的执行顺序是:

onCreate -> onRestart -> onStart -> onResume -> onPause -> onStop -> onDestory 
onCreate & onDestory // Activity 初始化和回收 
onStart & onStop // Activity 是否可见 
onResume & onPause // Activity 是否可交互

具体场景

  Activity 的首次启动

onCreate -> onStart -> onResume

  用户打开新的 Activity 或返回桌面

onPause -> onStop

  用户回到 Activity

onRestart -> onStart -> onResume

    当前 Activity 为 A,此时用户打开新的 Activity B,A 的 onPause 先于 B 的 onStart 执行,因为 Android 的设计原则:任何时刻都只有 1 个 Activity 处于 Resumed 阶段,如果 A 的 onPause 晚于 B 的 onResume 执行,那么会出现 A 和 B 同时处于 Resumed 阶段的瞬间,用户输入事件在此时不知道交付给哪个 Activity 来响应。

异常情况

  资源相关的系统配置发生改变导致 Activity 被杀死并重新创建

    最典型的情况就是用户旋转屏幕,回调顺序为

        onPause -> onStop -> onDestory -> onCreate -> onStart -> onResume 
onSaveInstanceState 👆                                     👇 onRestoreInstanceState

    其中 onSaveInstanceState 的调用时机在 onStop 前,onRestoreInstanceState 的调用时机在 onStart 后,我们在 Android Studio 空白 Activity 的模板代码中能看到

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);return insets;});}
}

    onCreate 回调方法的参数 Bundle 是用于存储 View 状态信息的轻量化键值对结构,在资源配置改变的异常行为发生时,系统会调用 onSaveInstanceState 回调方法来将此时 View 的内容保存成 Bundle 的形式,如果是新创建的 Activity,则 onCreate 的 Bundle 参数为 null,如果是异常情况重新创建,则 onCreate 的 Bundle 参数为 onSaveInstanceState 保存的 Bundle 实例。

    系统框架会在 onRestoreInstanceState 阶段自动恢复控件信息,开发者可以重写 onRestoreInstanceState 方法来拿取自己的业务逻辑数据,相应在 onSaveInstanceState 方法存储,onCreate 和 onRestoreInstanceState 传入的 Bundler 实例是同一个实例,它们都来自系统在异常销毁前 onSaveInstanceState 保存的状态。开发者应该在 onCreate 恢复不依赖于视图树的业务数据,同时在 onRestoreInstanceState 恢复必须依赖完整 View 初始化的状态信息。

  资源内存不足导致低优先级的 Activity 被杀死

    因为同样属于 Activity 被系统回收的异常销毁行为,所以数据恢复过程和资源配置改变的情况完全一致。Activity 的优先级从高到低划分即是生命周期回调的 3 个阶段:Resumed、Start 和 Stop,也就是焦点活动 > 可见活动 > 后台活动。如果一个进程中没有组件正在运行,那么这个进程会很快被系统杀死,比较好的方法是让该进程使用 Service 执行后台工作,这样可以避免被系统轻易杀死。

    如果开发者不希望系统配置改变时 Activity 重新创建,则可以使用 android:configChanges 属性来指定不希望重新创建的场景,如 andorid:configChanges="orientation" 可以避免在屏幕方向发生改变时重启 Activity,系统不再帮助自动恢复视图,开发者要重写 onConfigurationChanged 回调方法来手动更新布局资源,如果没有重写,则界面不会刷新,如从竖屏变横屏,布局依然会显示竖屏布局。

Activity LaunchMode

  standard 标准模式

    系统默认模式,每次启动 Activity 都会重新创建新的 Activity 实例,如果 A 启动 B,则 B 会运行在 A 所在的栈中,如果使用 ApplicationContext 启动标准模式的 Activity 时会报错,因为非 Activity 的 Context 没有任务栈。

  singleTop 栈顶复用模式

    如果启动的 Activity 已经位于任务栈的栈顶,那么该 Activity 不会被重新创建。

  singleTask 栈内复用模式

    只要启动的 Activity 在一个栈中存在,那么多次启动该 Activity 都不会重新创建实例,有多种情况

  1. 任务栈 S1 的情况是 ABC,D 以栈内复用模式请求启动进 S2,则系统会先创建 S2,然后再创建 D 的实例并将其放入 S2。

  2. 任务栈 S1 的情况是 ABC,D 以栈内复用模式请求启动进 S1,则系统会直接创建 D 的实例并将其放入 S1,完成操作后 S1 的情况是 ABCD。

  3. 任务栈 S1 的情况是 ADBC,D 以栈内复用模式请求启动进 S1,则系统会将 D 顶的所有 Activity 实例全部出栈,最终 S1 的情况是 AD。

  singleInstance 单实例模式

    要引入前台和后台的概念,前台任务栈是指栈顶 Activity 处于 Resumed 阶段的任务栈,前面我们提到,任意时刻处于 Resumed 阶段的 Activity 是唯一的,所以前台任务栈也是唯一的,后台任务栈是指栈顶 Activity 处于 Stopped 阶段的任务栈,后台任务栈可以有多个。每次启动 Activity,启动的 Activity 绝大多数情况都处于前台任务栈中。

    所以启动单实例模式的 Activity,系统会创建新的前台任务栈和 Activity 实例,并将该 Activity 放入前台任务栈,原本位于前台的任务栈进入后台。也因为前后台任务栈的概念,singleTask 模式有一种特殊情况

  • 前台任务栈情况 AB,后台任务栈情况 CD,C 以 singleTask 模式请求启动,那么 C 所在的后台任务栈首先进行出栈操作直到 C 位于栈顶,再将该任务栈直接切换到前台,此时前台任务栈的情况是 ABC

  allowTaskReparenting 属性

    Activity 所需要的任务栈即 TaskAffinity 偏好任务栈,默认是应用包名,在启动新的 Activity 时,如果 TaskAffinity 与目标任务栈匹配,则会尝试放入该栈里。allowTaskReparenting 属性仅在 Activity 启动后处于后台时有效,表示系统是否允许 Activity 从当前启动的任务栈迁移到与它的 TaskAffinity 匹配的任务栈。

    如果应用 A 启动应用 B 的某个 Activity,该 Activity 的 allowTaskReparenting 属性为 true、TaskAffinity 为默认的 B 包名,则应用 B 启动后该 Activity 会直接从 A 的任务栈转移到 B 的任务栈。

  指定启动模式

  1. AndroidMenifest.xml

    <activityandroid:name="main_activity"android:launchMode="singleTask" />
  2. Intent 标志位

    Intent intent = new Intent();
    intent.setClass(this, SecondActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);

          onNewIntent 是 Activity 的回调方法,用来处理已经存在的 Activity 再次被新的 Intent 启动的情况。标志位的优先级大于属性,二者同时存在时,以标志位情况为准。

      Flags 标志位

        FLAG_ACTIVITY_NEW_TASK

          指定 singleTask 启动模式。

        FLAG_ACTIVITY_SINGLE_TOP

          指定 singleTop 启动模式。

        FLAG_ACTIVITY_CLEAR_TOP

          具有此标志位的 Activity 启动时,所在任务栈顶所有 Activity 都要出栈。

        FLAG_ACTIIVITY_EXCLUDE_FROM_RECENTS

          具有此标志位的 Activity 不会出现在最近任务列表中,等效于 android:excludeFromRecents="true" 属性。

      IntentFilter 过滤规则

          启动 Activity 分为显式调用和隐式调用两种,二者共存的情况下以显式调用为主,隐式调用的 Intent 能够匹配启动组件的 IntentFilter 所设置的过滤信息。过滤信息分别有 action、category 和 data 等,可以有多个,同类别信息共同约束当前类别的匹配规则,只有完全匹配所有匹配规则才能成功启动目标 Activity,Activity 可以有多个 IntentFilter,一个 Intent 只要能匹配任意组 IntentFilter 即可成功启动对应 Activity。

        action 的匹配规则

          action 是字符串,系统预定义了部分 action,action 区分大小写,匹配要求 Intent 的 action 存在且与过滤规则中的其中一个 action 完全相同。

        category 的匹配规则

          category 也是字符串,与 action 不同的是,category 是对 action 行为的行为限制或使用场景约束,它要求 Intent 中如果含有 category,那么 Intent 所有的 category 都必须与过滤规则中的任意一个 category 相同,Intent 可以没有 category。所以只要 Intent 的 category 是 IntentFilter 的子集即可成功匹配。

         为什么没有 category 也可以匹配?原因是系统在启动 Activity 时会默认为 Intent 加上 android.intent.category.DEFAULT 这个 category,所以为了 Activity 能够接收隐式调用,必须在 intent-filter 指定 DEFAULT 类别。

        data 的匹配规则

      <data android:scheme="string"android:host="string"android:port="string"android:path="string"android:pathPattern="string"android:pathPrefix="string"android:mimeType="string" />

          data 由媒体类型 mimeType 和 URI 组成,URI 的结构是 <scheme>://<host>/[<path>|<pathPrefix>|<pathPattern>],data 的匹配规则与 action 类似,要求 Intent 中必须含有 data 数据且能够完全匹配过滤规则中的其中一个的 data。只设置 mimeType 部分时,系统在 Intent 内部会补齐空的 content://,对应 data 的 scheme 部分。

        匹配判断

          可以使用 PackageManage 或 Intent 的 resolveActivity 方法来判断是否有匹配的 Activity,如果没有则返回 null,有则返回最佳匹配的 Activity 信息,PackageManage 还有 queryIntentActivities 方法来返回所有匹配成功的 Activity 信息列表,方法签名分别是

      public abstract List<ResolveInfo> queryIntentActivities(Intent intent, int flags); 
      public abstract ResolveInfo resolveActivity(Intent intent, int flags);

      参考内容:Android 开发艺术探索 Ch.1

      http://www.dtcms.com/a/475735.html

      相关文章:

    • 网站开发设计方案书网站的搜索功能怎么做
    • 浙江省住房与城乡建设厅网站建设网站基础知识
    • 中国高清adidas网站如何自己申请商标注册
    • 有哪些做拎包入住的网站零基础jsp网站开发
    • CF1515E Phoenix and ComputersAC代码+详细注释
    • 相亲网站建设关键网站上传用什么软件做视频教程
    • 免费中学网站模板wordpress邀请有奖
    • 网站被降权了怎么办企业wap网站模板
    • 学院实训云上搭建集群
    • 潍坊设计网站建设wordpress 调查表 图片
    • 北流网站建设制作重庆ppt制作
    • 大型营销型网站制作南昌做网站需要多少钱
    • 简洁大气企业网站模板中国建设银行网站的发展
    • 个人建个网站需要多少钱最好的购物网站
    • 怎么自己做直播网站吗学校网站建设评比
    • 长治网站制作公司网站建设 入账
    • 东莞网站建设上科电脑云主机
    • 网站开发外包售后维护合同范本wordpress 充值积分
    • 嵌入式软件开发和硬件开发seo优化网站
    • ATA存储通信协议
    • 购物网站建设过程上海外贸商品交易会
    • Open CASCADE:模型带颜色导出至 STEP / IGES 文件
    • 电力建设监理招聘网站网站模板套餐
    • 东莞网站高端建设WordPress万级数据优化
    • 网站内容资源建设ps设计师网站
    • 源代码建网站如何用wordpress盈利
    • 销售型企业网站建设营销网站的目的
    • 网站开发有什么软件做网站会被捉吗
    • Controller中常见的一些注解
    • 中职网站建设与管理达州注册公司